import { create } from 'zustand';
import { persist } from 'zustand/middleware';

// Cada linea del carrito es independiente (uid propio), asi el MISMO producto
// puede ir varias veces con personalizaciones distintas: un perro "como me
// gusta" y otro "con todo" son dos lineas separadas.
export interface ItemCarrito {
  uid: string;
  producto_id: string;
  nombre: string;
  precio_usd: number;
  cantidad: number;
  nota?: string;
  // Opciones/contornos elegidos: nombres para el servidor (precio) y texto para mostrar.
  opcionesElegidas?: string[];
  // Cada eleccion con su grupo: el servidor cobra el extra del grupo correcto
  // (el mismo nombre puede ser gratis en un grupo y costar en otro).
  opcionesSel?: { g: string; o: string }[];
  opcionesTexto?: string;
}

function nuevoUid(): string {
  try {
    return crypto.randomUUID();
  } catch {
    return 'l' + Math.random().toString(36).slice(2) + Date.now().toString(36);
  }
}

const personalizado = (i: { nota?: string; opcionesTexto?: string }) =>
  !!((i.nota && i.nota.trim()) || i.opcionesTexto);

interface CarritoState {
  slug: string | null;
  items: ItemCarrito[];
  agregar: (slug: string, item: Omit<ItemCarrito, 'cantidad' | 'uid'>, cant?: number) => void;
  duplicar: (uid: string) => void;
  setCantidad: (uid: string, cant: number) => void;
  setNota: (uid: string, nota: string) => void;
  quitar: (uid: string) => void;
  limpiar: () => void;
  total: () => number;
  cantidadTotal: () => number;
}

export const useCarrito = create<CarritoState>()(
  persist(
    (set, get) => ({
      slug: null,
      items: [],
      agregar: (slug, item, cant = 1) =>
        set((s) => {
          // Si el carrito era de otro restaurante, se reinicia.
          const base = s.slug && s.slug !== slug ? [] : s.items;
          // El "+" simple agrupa con la linea sencilla del mismo producto. Si el
          // item trae opciones/nota, va como linea nueva (personalizacion aparte).
          const idx = personalizado(item)
            ? -1
            : base.findIndex((i) => i.producto_id === item.producto_id && !personalizado(i));
          let items: ItemCarrito[];
          if (idx >= 0) {
            items = base.map((i, k) => (k === idx ? { ...i, cantidad: i.cantidad + cant } : i));
          } else {
            items = [...base, { ...item, uid: nuevoUid(), cantidad: cant }];
          }
          return { slug, items };
        }),
      // "Agregar otro" del mismo producto como linea NUEVA para personalizarla aparte.
      duplicar: (uid) =>
        set((s) => {
          const l = s.items.find((i) => i.uid === uid);
          if (!l) return s;
          return {
            items: [
              ...s.items,
              { uid: nuevoUid(), producto_id: l.producto_id, nombre: l.nombre, precio_usd: l.precio_usd, cantidad: 1 },
            ],
          };
        }),
      setCantidad: (uid, cant) =>
        set((s) => ({
          items:
            cant <= 0
              ? s.items.filter((i) => i.uid !== uid)
              : s.items.map((i) => (i.uid === uid ? { ...i, cantidad: cant } : i)),
        })),
      setNota: (uid, nota) =>
        set((s) => ({ items: s.items.map((i) => (i.uid === uid ? { ...i, nota } : i)) })),
      quitar: (uid) => set((s) => ({ items: s.items.filter((i) => i.uid !== uid) })),
      limpiar: () => set({ items: [] }),
      total: () => get().items.reduce((a, i) => a + i.precio_usd * i.cantidad, 0),
      cantidadTotal: () => get().items.reduce((a, i) => a + i.cantidad, 0),
    }),
    { name: 'ff-carrito-v2' },
  ),
);
