"use client";

import React, { createContext, useContext, useState, useEffect, useMemo, useCallback } from "react";
import { BRAND } from "@/lib/brand";

export type Product = {
  id: string;
  name: string;
  description: string;
  price: number;
  /** Precio sin descuento, solo si hay una promoción vigente. */
  originalPrice?: number;
  image: string | null;
  stock: number;
  type?: string;
  category?: string | null;
  isLimited?: boolean;
  /** Boletos que otorga 1 unidad del pack */
  ticketCount?: number;
};

export type CartItem = Product & { quantity: number };

export type ShippingInfo = {
  address: string;
  comuna: string;
  region: string;
  notes: string;
};

export type PaymentMethod = "mercadopago" | "payku";

type CartContextType = {
  cart: CartItem[];
  isCartOpen: boolean;
  setIsCartOpen: (open: boolean) => void;
  addToCart: (product: Product) => void;
  removeFromCart: (id: string) => void;
  updateQuantity: (id: string, delta: number) => void;
  clearCart: () => void;
  total: number;
  hasPhysicalItems: boolean;
  hasTicketItems: boolean;
  guestEmail: string;
  setGuestEmail: (email: string) => void;
  buyerName: string;
  setBuyerName: (name: string) => void;
  buyerPhone: string;
  setBuyerPhone: (phone: string) => void;
  shipping: ShippingInfo;
  setShippingAddress: (address: string) => void;
  setShippingComuna: (comuna: string) => void;
  setShippingRegion: (region: string) => void;
  setShippingNotes: (notes: string) => void;
  paymentMethod: PaymentMethod;
  setPaymentMethod: (method: PaymentMethod) => void;
  isCheckoutLoading: boolean;
  handleCheckout: () => Promise<void>;
  syncProductPrices: (products: Product[]) => void;
};

const CartContext = createContext<CartContextType | undefined>(undefined);

const NAME_REGEX = /^[a-zA-ZáéíóúÁÉÍÓÚñÑüÜ\s\-']*$/;
const PHONE_LENGTH = 9;
const CART_STORAGE_KEY = BRAND.cartStorageKey;

export function cartHasPhysical(cart: CartItem[]): boolean {
  return cart.some((item) => item.type === "PHYSICAL");
}

export function CartProvider({ children }: { children: React.ReactNode }) {
  const [cart, setCart] = useState<CartItem[]>([]);
  const [isCartOpen, setIsCartOpen] = useState(false);
  const [isCheckoutLoading, setIsCheckoutLoading] = useState(false);

  const [guestEmail, setGuestEmail] = useState("");
  const [buyerName, setBuyerName] = useState("");
  const [buyerPhone, setBuyerPhone] = useState("");
  const [shipping, setShipping] = useState<ShippingInfo>({
    address: "",
    comuna: "",
    region: "",
    notes: "",
  });
  const [paymentMethod, setPaymentMethod] = useState<PaymentMethod>("mercadopago");

  const hasPhysicalItems = useMemo(() => cartHasPhysical(cart), [cart]);
  const hasTicketItems = useMemo(
    () => cart.some((item) => item.type !== "PHYSICAL"),
    [cart]
  );

  useEffect(() => {
    const savedCart = localStorage.getItem(CART_STORAGE_KEY);
    if (savedCart) {
      try {
        setCart(JSON.parse(savedCart));
      } catch (e) {
        console.error("Error loading cart from localStorage", e);
      }
    }
  }, []);

  const saveCart = (newCart: CartItem[]) => {
    setCart(newCart);
    localStorage.setItem(CART_STORAGE_KEY, JSON.stringify(newCart));
  };

  const addToCart = (product: Product) => {
    const existing = cart.find((item) => item.id === product.id);
    let newCart: CartItem[];
    const isStockLimited = product.type === "PHYSICAL" || product.isLimited;

    if (existing) {
      if (isStockLimited && existing.quantity >= product.stock) {
        alert(`Lo sentimos, no hay más stock disponible para "${product.name}".`);
        return;
      }
      newCart = cart.map((item) =>
        item.id === product.id ? { ...item, quantity: item.quantity + 1 } : item
      );
    } else {
      if (isStockLimited && product.stock <= 0) {
        alert(`Lo sentimos, el producto "${product.name}" se encuentra agotado.`);
        return;
      }
      newCart = [...cart, { ...product, quantity: 1 }];
    }
    saveCart(newCart);
    setIsCartOpen(true);
  };

  const removeFromCart = (id: string) => {
    saveCart(cart.filter((item) => item.id !== id));
  };

  const updateQuantity = (id: string, delta: number) => {
    const newCart = cart.map((item) => {
      if (item.id === id) {
        const isStockLimited = item.type === "PHYSICAL" || item.isLimited;
        const maxQty = isStockLimited ? item.stock : Number.MAX_SAFE_INTEGER;
        return { ...item, quantity: Math.min(maxQty, Math.max(1, item.quantity + delta)) };
      }
      return item;
    });
    saveCart(newCart);
  };

  const clearCart = () => {
    setCart([]);
    localStorage.removeItem(CART_STORAGE_KEY);
  };

  /** Actualiza precios guardados en el carrito con los vigentes (ej. al empezar/terminar un descuento). */
  const syncProductPrices = useCallback((products: Product[]) => {
    setCart((prev) => {
      let changed = false;
      const next = prev.map((item) => {
        const fresh = products.find((p) => p.id === item.id);
        if (!fresh) return item;
        if (fresh.price === item.price && fresh.originalPrice === item.originalPrice) return item;
        changed = true;
        return { ...item, price: fresh.price, originalPrice: fresh.originalPrice };
      });
      if (!changed) return prev;
      localStorage.setItem(CART_STORAGE_KEY, JSON.stringify(next));
      return next;
    });
  }, []);

  const total = cart.reduce((sum, item) => sum + item.price * item.quantity, 0);

  const handleCheckout = async () => {
    try {
      if (!guestEmail?.trim()) {
        alert("Por favor, ingresa tu correo para recibir tus boletos y/o comprobante.");
        return;
      }
      const nameTrim = buyerName.trim();
      if (!nameTrim || nameTrim.length < 2) {
        alert("Por favor, ingresa tu nombre (mínimo 2 caracteres).");
        return;
      }
      if (buyerPhone.length !== PHONE_LENGTH) {
        alert("El teléfono debe tener exactamente 9 dígitos.");
        return;
      }

      if (hasPhysicalItems) {
        if (shipping.address.trim().length < 5) {
          alert("Ingresa la dirección de envío (calle y número).");
          return;
        }
        if (!shipping.comuna.trim()) {
          alert("Ingresa la comuna de envío.");
          return;
        }
        if (!shipping.region.trim()) {
          alert("Selecciona la región de envío.");
          return;
        }
      }

      setIsCheckoutLoading(true);
      const res = await fetch("/api/checkout", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          items: cart.map(({ id, quantity }) => ({ id, quantity })),
          email: guestEmail?.trim(),
          name: nameTrim,
          phone: buyerPhone,
          paymentMethod,
          shipping: hasPhysicalItems
            ? {
                address: shipping.address.trim(),
                comuna: shipping.comuna.trim(),
                region: shipping.region.trim(),
                notes: shipping.notes.trim() || undefined,
              }
            : undefined,
        }),
      });
      const raw = await res.text();
      let data: { error?: string; redirectUrl?: string } = {};
      if (raw.trim()) {
        try {
          data = JSON.parse(raw) as typeof data;
        } catch {
          console.error("Checkout: respuesta no JSON", res.status, raw.slice(0, 500));
          alert(
            `El servidor respondió con un error no válido (HTTP ${res.status}). Suele ser un fallo temporal del hosting o del proxy. Prueba de nuevo; si sigue, revisa logs del servidor.`
          );
          return;
        }
      }

      if (!res.ok) {
        alert(data.error || "Ocurrió un error al procesar el pago");
        return;
      }

      if (data.redirectUrl) {
        clearCart();
        setIsCartOpen(false);
        window.location.href = data.redirectUrl;
        return;
      }

      alert("Compra procesada. Revisa tu correo para ver tus números y/o confirmación.");
      clearCart();
      setIsCartOpen(false);
    } catch (error) {
      console.error(error);
      alert("No se pudo contactar al servidor (red o corte de sesión). Revisa tu conexión e inténtalo de nuevo.");
    } finally {
      setIsCheckoutLoading(false);
    }
  };

  const updateName = (name: string) => {
    if (name.length <= 80 && (name === "" || NAME_REGEX.test(name))) {
      setBuyerName(name);
    }
  };

  const updatePhone = (phone: string) => {
    const cleanPhone = phone.replace(/\D/g, "");
    if (cleanPhone.length <= PHONE_LENGTH) {
      setBuyerPhone(cleanPhone);
    }
  };

  return (
    <CartContext.Provider
      value={{
        cart,
        isCartOpen,
        setIsCartOpen,
        addToCart,
        removeFromCart,
        updateQuantity,
        clearCart,
        total,
        hasPhysicalItems,
        hasTicketItems,
        guestEmail,
        setGuestEmail,
        buyerName,
        setBuyerName: updateName,
        buyerPhone,
        setBuyerPhone: updatePhone,
        shipping,
        setShippingAddress: (address) => setShipping((s) => ({ ...s, address })),
        setShippingComuna: (comuna) => setShipping((s) => ({ ...s, comuna })),
        setShippingRegion: (region) => setShipping((s) => ({ ...s, region })),
        setShippingNotes: (notes) => setShipping((s) => ({ ...s, notes })),
        paymentMethod,
        setPaymentMethod,
        isCheckoutLoading,
        handleCheckout,
        syncProductPrices,
      }}
    >
      {children}
    </CartContext.Provider>
  );
}

export function useCart() {
  const context = useContext(CartContext);
  if (!context) {
    throw new Error("useCart must be used within a CartProvider");
  }
  return context;
}
