import { useRef, useState } from 'react';
import { useQuery, useQueryClient } from '@tanstack/react-query';
import type { Restaurante } from '@gustito/shared';
import { supabase } from '../lib/supabase';
import SimuladorCombinacion from '../components/SimuladorCombinacion';
import type { GrupoCfg, RecetaDe } from '../components/SimuladorCombinacion';

// CEREBRO DE COSTOS (fase 1): cuanto le VALE cada plato y cuanto gana.
// La IA solo captura (receta conversada + factura por foto); el costo lo
// calcula la BD (costos_productos). Costo de ingrediente = ultima compra
// (costo de reposicion: con la inflacion es el que importa).

type FilaCosto = {
  producto_id: string;
  nombre: string;
  precio_usd: number;
  costo_usd: number;
  margen_usd: number;
  margen_pct: number | null;
  ingredientes: number;
  sin_precio: number;
  opciones_con_receta: number;
  opciones_total: number;
};

// Grupos de opciones del producto (proteinas, contornos...) para que el chat
// pregunte por las porciones de CADA opcion, no solo por la base del plato.
type GrupoOpciones = { nombre: string; max?: number | null; opciones: string[] };

// Renglon de receta con el costo del ingrediente pegado (embed de PostgREST).
type RenglonCosto = {
  producto_id: string;
  opcion: string | null;
  cantidad_base: number;
  ingredientes: { costo_por_unidad: number } | null;
};

type Ingrediente = {
  id: string;
  nombre: string;
  unidad_base: 'g' | 'ml' | 'unidad';
  costo_por_unidad: number;
  costo_actualizado_en: string | null;
};

type MensajeChat = { de: 'dueno' | 'ia'; texto: string };
type RenglonReceta = { opcion: string; ingrediente_id: string | null; nombre: string; unidad_base: string; cantidad_base: number };
type ItemFactura = {
  descripcion: string;
  cantidad_base: number;
  unidad_base: string;
  costo_total: number;
  moneda: 'bs' | 'usd';
  ingrediente_id: string | null;
  nombre_nuevo: string | null;
  incluir?: boolean;
};

const usd = (n: number) => `$${Number(n).toFixed(2)}`;

// El costo por unidad base (ej $0.0021 por gramo) es ilegible: se muestra en
// la unidad grande (kilo/litro/unidad).
function costoLegible(i: Ingrediente): string {
  if (i.costo_por_unidad <= 0) return 'sin precio';
  if (i.unidad_base === 'g') return `${usd(i.costo_por_unidad * 1000)}/kg`;
  if (i.unidad_base === 'ml') return `${usd(i.costo_por_unidad * 1000)}/L`;
  return `${usd(i.costo_por_unidad)}/und`;
}

function cantidadLegible(cantidad: number, unidad: string): string {
  if (unidad === 'g') return cantidad >= 1000 ? `${(cantidad / 1000).toFixed(2)} kg` : `${cantidad} g`;
  if (unidad === 'ml') return cantidad >= 1000 ? `${(cantidad / 1000).toFixed(2)} L` : `${cantidad} ml`;
  return `${cantidad} und`;
}

function semaforo(f: FilaCosto): { color: string; label: string } {
  if (!f.ingredientes) return { color: '#8A8FAF', label: 'Sin receta' };
  if (f.sin_precio > 0) return { color: '#FBBF24', label: `${f.sin_precio} sin precio` };
  if (f.opciones_total > 0 && f.opciones_con_receta === 0) return { color: '#FBBF24', label: 'Faltan las opciones' };
  if (f.margen_pct == null) return { color: '#8A8FAF', label: 'Sin precio de venta' };
  if (f.margen_pct >= 60) return { color: '#22C55E', label: 'Sano' };
  if (f.margen_pct >= 40) return { color: '#FBBF24', label: 'Apretado' };
  return { color: '#EF4444', label: 'Pierdes plata' };
}

export default function Costos({ restaurante, marca, txtMarca }: { restaurante: Restaurante; marca: string; txtMarca: string }) {
  const qc = useQueryClient();
  const [recetaDe, setRecetaDe] = useState<FilaCosto | null>(null);
  const [simularDe, setSimularDe] = useState<FilaCosto | null>(null);
  const [facturaAbierta, setFacturaAbierta] = useState(false);

  const costosQ = useQuery({
    queryKey: ['costos', restaurante.id],
    queryFn: async () => {
      const { data, error } = await supabase.rpc('costos_productos', { p_restaurante_id: restaurante.id });
      if (error) throw error;
      return (data ?? []) as FilaCosto[];
    },
  });

  // Grupos de opciones de cada producto. Salen dos vistas del mismo dato: la
  // del chat (solo nombres, es lo que espera la EF) y la completa (con tipo y
  // precio_extra) que necesita el simulador para cobrar bien cada combinacion.
  const opcionesQ = useQuery({
    queryKey: ['costos-opciones', restaurante.id],
    queryFn: async () => {
      const { data, error } = await supabase
        .from('productos')
        .select('id,opciones')
        .eq('restaurante_id', restaurante.id);
      if (error) throw error;
      const chat = new Map<string, GrupoOpciones[]>();
      const full = new Map<string, GrupoCfg[]>();
      for (const p of data ?? []) {
        const grupos = (Array.isArray(p.opciones) ? p.opciones : []) as unknown as {
          nombre?: string;
          tipo?: string;
          max?: number | null;
          opciones?: { nombre?: string; precio_extra?: number }[];
        }[];
        const validos = grupos.filter((g) => g?.nombre && Array.isArray(g.opciones) && g.opciones.length);
        chat.set(
          p.id,
          validos.map((g) => ({
            nombre: String(g.nombre),
            max: g.max ?? 1,
            opciones: (g.opciones ?? []).map((o) => String(o?.nombre ?? '')).filter(Boolean),
          })),
        );
        full.set(
          p.id,
          validos.map((g) => ({
            nombre: String(g.nombre),
            tipo: String(g.tipo ?? 'multi'),
            max: g.max ?? null,
            opciones: (g.opciones ?? [])
              .filter((o) => o?.nombre)
              .map((o) => ({ nombre: String(o.nombre), precio_extra: Number(o.precio_extra) || 0 })),
          })),
        );
      }
      return { chat, full };
    },
  });

  // Costo de la base y de CADA opcion (para el simulador). La tabla de arriba
  // muestra el plato tipico; esto permite armar una combinacion puntual.
  const recetasQ = useQuery({
    queryKey: ['recetas-costo', restaurante.id],
    queryFn: async () => {
      const { data, error } = await supabase
        .from('recetas_productos')
        .select('producto_id,opcion,cantidad_base,ingredientes!inner(costo_por_unidad),productos!inner(restaurante_id)')
        .eq('productos.restaurante_id', restaurante.id);
      if (error) throw error;
      const mapa = new Map<string, RecetaDe>();
      for (const r of (data ?? []) as unknown as RenglonCosto[]) {
        let prod = mapa.get(r.producto_id);
        if (!prod) {
          prod = { base: { costo: 0, sinPrecio: 0 }, opciones: new Map() };
          mapa.set(r.producto_id, prod);
        }
        const unitario = Number(r.ingredientes?.costo_por_unidad) || 0;
        const monto = (Number(r.cantidad_base) || 0) * unitario;
        const destino = r.opcion
          ? prod.opciones.get(r.opcion) ?? { costo: 0, sinPrecio: 0 }
          : prod.base;
        destino.costo += monto;
        if (unitario <= 0) destino.sinPrecio += 1;
        if (r.opcion) prod.opciones.set(r.opcion, destino);
      }
      return mapa;
    },
  });

  const ingredientesQ = useQuery({
    queryKey: ['ingredientes', restaurante.id],
    queryFn: async () => {
      const { data, error } = await supabase
        .from('ingredientes')
        .select('id,nombre,unidad_base,costo_por_unidad,costo_actualizado_en')
        .eq('restaurante_id', restaurante.id)
        .eq('activo', true)
        .order('nombre');
      if (error) throw error;
      return (data ?? []) as Ingrediente[];
    },
  });

  const filas = costosQ.data ?? [];
  const ingredientes = ingredientesQ.data ?? [];
  const conReceta = filas.filter((f) => f.ingredientes > 0);
  const completos = conReceta.filter((f) => f.sin_precio === 0 && f.margen_pct != null);
  const enRojo = completos.filter((f) => (f.margen_pct ?? 0) < 40);
  const margenProm = completos.length
    ? completos.reduce((s, f) => s + (f.margen_pct ?? 0), 0) / completos.length
    : null;

  const refrescar = () => {
    qc.invalidateQueries({ queryKey: ['costos', restaurante.id] });
    qc.invalidateQueries({ queryKey: ['ingredientes', restaurante.id] });
    qc.invalidateQueries({ queryKey: ['recetas-costo', restaurante.id] });
  };

  return (
    <div className="space-y-5">
      <div className="flex items-center justify-between gap-2 flex-wrap">
        <h1 className="text-xl font-extrabold">Costos y márgenes</h1>
        <button
          onClick={() => setFacturaAbierta(true)}
          className="rounded-xl px-4 py-2 text-sm font-bold"
          style={{ background: marca, color: txtMarca }}
        >
          📷 Subir factura de compras
        </button>
      </div>

      <div className="grid grid-cols-3 gap-2 sm:gap-3">
        <Resumen label="Platos con receta" valor={`${conReceta.length}/${filas.length}`} color="#FFFFFF" />
        <Resumen label="Margen promedio" valor={margenProm != null ? `${margenProm.toFixed(0)}%` : '—'} color={margenProm != null && margenProm >= 60 ? '#22C55E' : '#FBBF24'} />
        <Resumen label="En rojo" valor={enRojo.length} color={enRojo.length ? '#EF4444' : '#22C55E'} />
      </div>

      <p className="text-sm text-niebla">
        El Cerebro te entrevista una vez por plato para armar la receta, y los precios entran solos con la foto de cada factura.
        El costo usa tu última compra (lo que te costaría reponerlo hoy).
      </p>
      <p className="rounded-2xl bg-superficie p-3 text-xs text-niebla ring-1 ring-white/10">
        🔒 Tus precios de venta no se mueven solos. Subir una factura solo actualiza lo que te cuestan tus
        insumos; lo que le cobras al cliente lo cambias tú en Menú, cuando tú quieras.
      </p>

      {/* ===== Platos ===== */}
      <div className="divide-y divide-white/10 overflow-hidden rounded-2xl bg-superficie ring-1 ring-white/10">
        {filas.map((f) => {
          const s = semaforo(f);
          return (
            <div key={f.producto_id} className="flex items-center gap-3 px-4 py-3">
              <span className="h-2.5 w-2.5 shrink-0 rounded-full" style={{ background: s.color }} />
              <div className="min-w-0 flex-1">
                <p className="truncate font-semibold">{f.nombre}</p>
                <p className="text-xs text-niebla">
                  {f.ingredientes
                    ? `Cuesta ${usd(f.costo_usd)} · vendes en ${usd(f.precio_usd)} · ganas ${usd(f.margen_usd)}${f.margen_pct != null ? ` (${f.margen_pct}%)` : ''} · ${s.label}` +
                      (f.opciones_total > 0 ? ` · opciones ${f.opciones_con_receta}/${f.opciones_total}` : '')
                    : 'Sin receta todavía'}
                </p>
              </div>
              <span className="flex shrink-0 gap-1.5">
                {f.ingredientes > 0 && (opcionesQ.data?.full.get(f.producto_id)?.length ?? 0) > 0 && (
                  <button
                    onClick={() => setSimularDe(f)}
                    className="rounded-lg px-3 py-1.5 text-xs font-bold ring-1 ring-white/15 hover:bg-white/5"
                  >
                    Simular
                  </button>
                )}
                <button
                  onClick={() => setRecetaDe(f)}
                  className="rounded-lg px-3 py-1.5 text-xs font-bold ring-1 ring-white/15 hover:bg-white/5"
                >
                  {f.ingredientes ? 'Receta' : 'Armar receta'}
                </button>
              </span>
            </div>
          );
        })}
        {!filas.length && (
          <p className="p-6 text-center text-sm text-niebla">Aún no tienes productos. Créalos en la sección Menú.</p>
        )}
      </div>

      {/* ===== Ingredientes ===== */}
      <h2 className="text-base font-extrabold">Ingredientes y precios</h2>
      <div className="divide-y divide-white/10 overflow-hidden rounded-2xl bg-superficie ring-1 ring-white/10">
        {ingredientes.map((i) => (
          <FilaIngrediente key={i.id} ing={i} onCambio={refrescar} />
        ))}
        {!ingredientes.length && (
          <p className="p-6 text-center text-sm text-niebla">
            Todavía no hay ingredientes. Salen solos al armar recetas o al subir tu primera factura.
          </p>
        )}
      </div>

      {simularDe && (
        <SimuladorCombinacion
          producto={{ producto_id: simularDe.producto_id, nombre: simularDe.nombre, precio_usd: simularDe.precio_usd }}
          grupos={(opcionesQ.data?.full.get(simularDe.producto_id) ?? []) as GrupoCfg[]}
          receta={(recetasQ.data?.get(simularDe.producto_id) ?? { base: { costo: 0, sinPrecio: 0 }, opciones: new Map() }) as RecetaDe}
          marca={marca}
          txtMarca={txtMarca}
          onCerrar={() => setSimularDe(null)}
        />
      )}
      {recetaDe && (
        <ModalReceta
          producto={recetaDe}
          grupos={opcionesQ.data?.chat.get(recetaDe.producto_id) ?? []}
          restauranteId={restaurante.id}
          ingredientes={ingredientes}
          marca={marca}
          txtMarca={txtMarca}
          onCerrar={(cambio) => {
            setRecetaDe(null);
            if (cambio) refrescar();
          }}
        />
      )}
      {facturaAbierta && (
        <ModalFactura
          restaurante={restaurante}
          ingredientes={ingredientes}
          marca={marca}
          txtMarca={txtMarca}
          onCerrar={(cambio) => {
            setFacturaAbierta(false);
            if (cambio) refrescar();
          }}
        />
      )}
    </div>
  );
}

function Resumen({ label, valor, color }: { label: string; valor: string | number; color: string }) {
  return (
    <div className="rounded-2xl bg-superficie p-3 ring-1 ring-white/10">
      <p className="text-lg font-extrabold" style={{ color }}>{valor}</p>
      <p className="text-xs text-niebla">{label}</p>
    </div>
  );
}

function FilaIngrediente({ ing, onCambio }: { ing: Ingrediente; onCambio: () => void }) {
  const [editando, setEditando] = useState(false);
  const [valor, setValor] = useState('');
  const [guardando, setGuardando] = useState(false);

  // El dueno edita en la unidad LEGIBLE ($/kg, $/L, $/und); se guarda en base.
  async function guardar() {
    const n = Number(valor.replace(',', '.'));
    if (!(n >= 0)) return;
    setGuardando(true);
    const porBase = ing.unidad_base === 'unidad' ? n : n / 1000;
    await supabase
      .from('ingredientes')
      .update({ costo_por_unidad: porBase, costo_actualizado_en: new Date().toISOString() })
      .eq('id', ing.id);
    setGuardando(false);
    setEditando(false);
    onCambio();
  }

  return (
    <div className="flex items-center gap-3 px-4 py-2.5">
      <div className="min-w-0 flex-1">
        <p className="truncate text-sm font-semibold">{ing.nombre}</p>
        <p className="text-xs text-niebla">
          {costoLegible(ing)}
          {ing.costo_actualizado_en ? ` · actualizado ${new Date(ing.costo_actualizado_en).toLocaleDateString('es-VE')}` : ''}
        </p>
      </div>
      {editando ? (
        <div className="flex items-center gap-1.5">
          <input
            autoFocus
            inputMode="decimal"
            value={valor}
            onChange={(e) => setValor(e.target.value)}
            placeholder={ing.unidad_base === 'unidad' ? '$/und' : ing.unidad_base === 'ml' ? '$/L' : '$/kg'}
            className="w-24 rounded-lg bg-black/30 px-2 py-1.5 text-sm ring-1 ring-white/20"
          />
          <button onClick={guardar} disabled={guardando} className="rounded-lg bg-green-600 px-2.5 py-1.5 text-xs font-bold text-white disabled:opacity-60">
            {guardando ? '...' : 'OK'}
          </button>
          <button onClick={() => setEditando(false)} className="rounded-lg px-2 py-1.5 text-xs ring-1 ring-white/15">✕</button>
        </div>
      ) : (
        <button onClick={() => { setEditando(true); setValor(''); }} className="rounded-lg px-3 py-1.5 text-xs font-bold ring-1 ring-white/15 hover:bg-white/5">
          Precio
        </button>
      )}
    </div>
  );
}

// ===== Chat de receta (la IA entrevista; al final se revisa y se guarda) =====
function ModalReceta({
  producto,
  grupos,
  restauranteId,
  ingredientes,
  marca,
  txtMarca,
  onCerrar,
}: {
  producto: FilaCosto;
  grupos: GrupoOpciones[];
  restauranteId: string;
  ingredientes: Ingrediente[];
  marca: string;
  txtMarca: string;
  onCerrar: (cambio: boolean) => void;
}) {
  const [mensajes, setMensajes] = useState<MensajeChat[]>([]);
  const [texto, setTexto] = useState('');
  const [pensando, setPensando] = useState(false);
  const [receta, setReceta] = useState<RenglonReceta[] | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [guardando, setGuardando] = useState(false);
  // Minimizado: el chat se aparta sin perder la conversacion (chip flotante).
  const [min, setMin] = useState(false);
  const arrancado = useRef(false);

  async function llamarIA(historial: MensajeChat[]) {
    setPensando(true);
    setError(null);
    try {
      const { data: ses } = await supabase.auth.getSession();
      const res = await fetch(`${import.meta.env.VITE_SUPABASE_URL}/functions/v1/cerebro-receta`, {
        method: 'POST',
        headers: {
          Authorization: `Bearer ${ses.session?.access_token}`,
          apikey: import.meta.env.VITE_SUPABASE_ANON_KEY,
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          producto: { nombre: producto.nombre },
          grupos,
          ingredientes: ingredientes.map((i) => ({ id: i.id, nombre: i.nombre, unidad_base: i.unidad_base })),
          mensajes: historial,
        }),
      });
      const j = await res.json();
      if (!res.ok) throw new Error(j.error || 'La IA no respondió');
      if (j.listo && Array.isArray(j.receta)) {
        setReceta(j.receta as RenglonReceta[]);
        setMensajes([...historial, { de: 'ia', texto: j.comentario || 'Listo, revisa la receta. Si falta algo, dímelo aquí abajo.' }]);
      } else {
        setMensajes([...historial, { de: 'ia', texto: j.pregunta as string }]);
      }
    } catch (e) {
      setError((e as Error).message);
    } finally {
      setPensando(false);
    }
  }

  if (!arrancado.current) {
    arrancado.current = true;
    void llamarIA([]);
  }

  function enviar() {
    const t = texto.trim();
    if (!t || pensando) return;
    // Si ya hay receta en pantalla, la IA la recibe como contexto para AJUSTARLA
    // (nada de trancarse: "agrégale las proteínas" debe funcionar).
    const historial: MensajeChat[] = [...mensajes];
    if (receta) historial.push({ de: 'ia', texto: 'RECETA ACTUAL: ' + JSON.stringify(receta) });
    historial.push({ de: 'dueno', texto: t });
    setMensajes(historial);
    setTexto('');
    void llamarIA(historial);
  }

  async function guardarReceta() {
    if (!receta?.length) return;
    setGuardando(true);
    setError(null);
    try {
      // 1) Crear los ingredientes nuevos (los que no matchearon con existentes).
      const renglones: { ingrediente_id: string; cantidad_base: number; opcion: string }[] = [];
      for (const r of receta) {
        if (r.ingrediente_id) {
          renglones.push({ ingrediente_id: r.ingrediente_id, cantidad_base: r.cantidad_base, opcion: r.opcion ?? '' });
          continue;
        }
        const { data, error: e } = await supabase
          .from('ingredientes')
          .upsert(
            { restaurante_id: restauranteId, nombre: r.nombre, unidad_base: r.unidad_base },
            { onConflict: 'restaurante_id,nombre', ignoreDuplicates: false },
          )
          .select('id')
          .single();
        if (e || !data) throw new Error(e?.message || 'No se pudo crear el ingrediente ' + r.nombre);
        renglones.push({ ingrediente_id: data.id, cantidad_base: r.cantidad_base, opcion: r.opcion ?? '' });
      }
      // Mismo ingrediente en base y en una opcion es valido; duplicado exacto no.
      const vistos = new Set<string>();
      const unicos = renglones.filter((r) => {
        const k = r.ingrediente_id + '|' + r.opcion;
        if (vistos.has(k)) return false;
        vistos.add(k);
        return true;
      });
      // 2) Reemplazar la receta del plato.
      await supabase.from('recetas_productos').delete().eq('producto_id', producto.producto_id);
      const { error: e2 } = await supabase.from('recetas_productos').insert(
        unicos.map((r) => ({ producto_id: producto.producto_id, ...r })),
      );
      if (e2) throw new Error(e2.message);
      onCerrar(true);
    } catch (e) {
      setError((e as Error).message);
    } finally {
      setGuardando(false);
    }
  }

  // Minimizado: solo el chip flotante; la conversacion sigue viva detras.
  if (min) {
    return (
      <button
        onClick={() => setMin(false)}
        className="fixed bottom-20 right-4 z-[1600] flex items-center gap-2 rounded-full px-4 py-2.5 text-sm font-bold shadow-2xl ring-2 ring-white/20"
        style={{ background: marca, color: txtMarca }}
      >
        🧮 Receta · {producto.nombre} {pensando ? '· pensando...' : ''}
      </button>
    );
  }

  return (
    <>
      <div className="fixed inset-0 z-[1500] bg-black/60" onClick={() => setMin(true)} />
      <div className="fixed inset-x-3 top-[6%] bottom-[6%] z-[1600] mx-auto flex max-w-lg flex-col overflow-hidden rounded-2xl ring-1 ring-white/15" style={{ background: '#12142B' }}>
        <div className="flex items-center justify-between px-4 py-3" style={{ background: marca, color: txtMarca }}>
          <p className="font-extrabold">Receta · {producto.nombre}</p>
          <span className="flex items-center gap-1">
            <button onClick={() => setMin(true)} title="Minimizar" className="rounded-lg px-2.5 text-xl font-bold leading-none hover:bg-black/10">–</button>
            <button onClick={() => onCerrar(false)} title="Cerrar" className="rounded-lg px-2 text-xl font-bold leading-none hover:bg-black/10">✕</button>
          </span>
        </div>

        <div className="flex-1 space-y-2 overflow-y-auto p-4">
          {mensajes.map((m, i) => (
            <div key={i} className={`max-w-[85%] rounded-2xl px-3 py-2 text-sm ${m.de === 'ia' ? 'bg-superficie ring-1 ring-white/10' : 'ml-auto text-black'}`} style={m.de === 'dueno' ? { background: marca, color: txtMarca } : undefined}>
              {m.texto}
            </div>
          ))}
          {pensando && <p className="text-xs text-niebla">El Cerebro está pensando...</p>}
          {error && <p className="text-xs text-red-400">{error}</p>}

          {receta && (
            <div className="rounded-2xl bg-superficie p-3 ring-1 ring-white/10">
              <p className="mb-2 text-sm font-bold">Receta (revísala; puedes seguir pidiéndole ajustes abajo):</p>
              {(() => {
                const secciones: { titulo: string; items: { r: RenglonReceta; idx: number }[] }[] = [];
                const base = receta.map((r, idx) => ({ r, idx })).filter((x) => !x.r.opcion);
                if (base.length) secciones.push({ titulo: 'Siempre lleva', items: base });
                for (const g of grupos) {
                  const items = receta.map((r, idx) => ({ r, idx })).filter((x) => g.opciones.includes(x.r.opcion));
                  if (items.length) secciones.push({ titulo: g.nombre, items });
                }
                const enGrupos = new Set(secciones.flatMap((s) => s.items.map((x) => x.idx)));
                const sueltos = receta.map((r, idx) => ({ r, idx })).filter((x) => !enGrupos.has(x.idx));
                if (sueltos.length) secciones.push({ titulo: 'Otros', items: sueltos });
                return secciones.map((s) => (
                  <div key={s.titulo} className="mb-2">
                    <p className="text-xs font-bold uppercase tracking-wide text-niebla">{s.titulo}</p>
                    {s.items.map(({ r, idx }) => (
                      <div key={idx} className="flex items-center gap-2 py-1 text-sm">
                        <span className="flex-1 truncate">{r.opcion ? `${r.opcion} · ${r.nombre}` : r.nombre}</span>
                        <input
                          inputMode="decimal"
                          value={String(r.cantidad_base)}
                          onChange={(e) => {
                            const v = Number(e.target.value.replace(',', '.'));
                            setReceta(receta.map((x, j) => (j === idx ? { ...x, cantidad_base: v > 0 ? v : x.cantidad_base } : x)));
                          }}
                          className="w-20 rounded-lg bg-black/30 px-2 py-1 text-right text-sm ring-1 ring-white/20"
                        />
                        <span className="w-10 text-xs text-niebla">{r.unidad_base}</span>
                        <button onClick={() => setReceta(receta.filter((_, j) => j !== idx))} className="text-xs text-red-400">✕</button>
                      </div>
                    ))}
                  </div>
                ));
              })()}
              <button
                onClick={guardarReceta}
                disabled={guardando || !receta.length}
                className="mt-2 w-full rounded-xl py-2.5 text-sm font-bold disabled:opacity-60"
                style={{ background: marca, color: txtMarca }}
              >
                {guardando ? 'Guardando...' : 'Guardar receta'}
              </button>
            </div>
          )}
        </div>

        {/* El input NUNCA se esconde: con la receta en pantalla se le siguen
            pidiendo ajustes ("agrégale las proteínas", "la gallina lleva 120"). */}
        <div className="flex gap-2 border-t border-white/10 p-3">
          <input
            value={texto}
            onChange={(e) => setTexto(e.target.value)}
            onKeyDown={(e) => e.key === 'Enter' && enviar()}
            placeholder={receta ? '¿Algo que ajustar? díselo aquí...' : 'Respóndele como hablas: un paquete rinde pa 16...'}
            className="flex-1 rounded-xl bg-black/30 px-3 py-2.5 text-sm ring-1 ring-white/20"
          />
          <button onClick={enviar} disabled={pensando || !texto.trim()} className="rounded-xl px-4 text-sm font-bold disabled:opacity-60" style={{ background: marca, color: txtMarca }}>
            Enviar
          </button>
        </div>
      </div>
    </>
  );
}

// ===== Factura por foto (la IA extrae; se confirma renglon por renglon) =====
function ModalFactura({
  restaurante,
  ingredientes,
  marca,
  txtMarca,
  onCerrar,
}: {
  restaurante: Restaurante;
  ingredientes: Ingrediente[];
  marca: string;
  txtMarca: string;
  onCerrar: (cambio: boolean) => void;
}) {
  const [items, setItems] = useState<ItemFactura[] | null>(null);
  const [leyendo, setLeyendo] = useState(false);
  const [guardando, setGuardando] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const tasa = Number(restaurante.tasa_bs) || 0;

  async function procesarFoto(file: File) {
    setLeyendo(true);
    setError(null);
    try {
      const b64 = await new Promise<string>((resolve, reject) => {
        const fr = new FileReader();
        fr.onload = () => resolve(String(fr.result).split(',')[1] ?? '');
        fr.onerror = reject;
        fr.readAsDataURL(file);
      });
      const { data: ses } = await supabase.auth.getSession();
      const res = await fetch(`${import.meta.env.VITE_SUPABASE_URL}/functions/v1/cerebro-factura`, {
        method: 'POST',
        headers: {
          Authorization: `Bearer ${ses.session?.access_token}`,
          apikey: import.meta.env.VITE_SUPABASE_ANON_KEY,
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          imagen_base64: b64,
          mime_type: file.type || 'image/jpeg',
          ingredientes: ingredientes.map((i) => ({ id: i.id, nombre: i.nombre, unidad_base: i.unidad_base })),
        }),
      });
      const j = await res.json();
      if (!res.ok) throw new Error(j.error || 'La IA no pudo leer la factura');
      if (!Array.isArray(j.items) || !j.items.length) throw new Error('No se encontraron renglones de compra en la foto.');
      setItems((j.items as ItemFactura[]).map((x) => ({ ...x, incluir: true })));
    } catch (e) {
      setError((e as Error).message);
    } finally {
      setLeyendo(false);
    }
  }

  function costoUsd(it: ItemFactura): number {
    if (it.moneda === 'usd') return it.costo_total;
    return tasa > 0 ? it.costo_total / tasa : 0;
  }

  async function registrar() {
    if (!items) return;
    const activos = items.filter((i) => i.incluir);
    if (!activos.length) return;
    if (activos.some((i) => i.moneda === 'bs') && !(tasa > 0)) {
      setError('La factura está en bolívares y el negocio no tiene tasa configurada.');
      return;
    }
    setGuardando(true);
    setError(null);
    try {
      for (const it of activos) {
        let ingredienteId = it.ingrediente_id;
        if (!ingredienteId) {
          const { data, error: e } = await supabase
            .from('ingredientes')
            .upsert(
              { restaurante_id: restaurante.id, nombre: it.nombre_nuevo || it.descripcion.slice(0, 60), unidad_base: it.unidad_base },
              { onConflict: 'restaurante_id,nombre', ignoreDuplicates: false },
            )
            .select('id')
            .single();
          if (e || !data) throw new Error(e?.message || 'No se pudo crear el ingrediente');
          ingredienteId = data.id;
        }
        const { error: e2 } = await supabase.rpc('registrar_compra_ingrediente', {
          p_ingrediente_id: ingredienteId,
          p_cantidad_base: it.cantidad_base,
          p_costo_total_usd: Math.round(costoUsd(it) * 100) / 100,
          p_descripcion: it.descripcion,
          p_fuente: 'factura_ia',
        });
        if (e2) throw new Error(e2.message);
      }
      onCerrar(true);
    } catch (e) {
      setError((e as Error).message);
    } finally {
      setGuardando(false);
    }
  }

  return (
    <>
      <div className="fixed inset-0 z-[1500] bg-black/60" onClick={() => onCerrar(false)} />
      <div className="fixed inset-x-3 top-[6%] bottom-[6%] z-[1600] mx-auto flex max-w-lg flex-col overflow-hidden rounded-2xl ring-1 ring-white/15" style={{ background: '#12142B' }}>
        <div className="flex items-center justify-between px-4 py-3" style={{ background: marca, color: txtMarca }}>
          <p className="font-extrabold">Factura de compras</p>
          <button onClick={() => onCerrar(false)} className="text-xl font-bold leading-none">✕</button>
        </div>

        <div className="flex-1 space-y-3 overflow-y-auto p-4">
          {!items && (
            <label className="block cursor-pointer rounded-2xl border-2 border-dashed border-white/20 p-8 text-center text-sm text-niebla hover:bg-white/5">
              {leyendo ? 'El Cerebro está leyendo la factura...' : 'Toca aquí y elige la FOTO de la factura, recibo o cuaderno de compras'}
              <input
                type="file"
                accept="image/*"
                className="hidden"
                disabled={leyendo}
                onChange={(e) => e.target.files?.[0] && void procesarFoto(e.target.files[0])}
              />
            </label>
          )}
          {error && <p className="text-sm text-red-400">{error}</p>}

          {items && (
            <>
              <p className="text-xs text-niebla">
                Revisa cada renglón antes de registrar. Los montos en Bs se convierten con tu tasa ({tasa > 0 ? `Bs ${tasa}` : 'SIN TASA'}).
              </p>
              {items.map((it, i) => (
                <div key={i} className={`rounded-xl p-3 ring-1 ring-white/10 ${it.incluir ? 'bg-superficie' : 'bg-superficie/40 opacity-60'}`}>
                  <div className="flex items-start gap-2">
                    <input
                      type="checkbox"
                      checked={!!it.incluir}
                      onChange={(e) => setItems(items.map((x, j) => (j === i ? { ...x, incluir: e.target.checked } : x)))}
                      className="mt-1 h-4 w-4"
                    />
                    <div className="min-w-0 flex-1">
                      <p className="truncate text-sm font-semibold">
                        {it.ingrediente_id
                          ? ingredientes.find((g) => g.id === it.ingrediente_id)?.nombre
                          : `${it.nombre_nuevo} (nuevo)`}
                      </p>
                      <p className="text-xs text-niebla">{it.descripcion}</p>
                      <p className="text-xs text-niebla">
                        {cantidadLegible(it.cantidad_base, it.unidad_base)} · {it.moneda === 'bs' ? `Bs ${it.costo_total.toLocaleString('es-VE')}` : usd(it.costo_total)}
                        {it.moneda === 'bs' && tasa > 0 ? ` ≈ ${usd(costoUsd(it))}` : ''}
                      </p>
                    </div>
                  </div>
                </div>
              ))}
              <button
                onClick={registrar}
                disabled={guardando || !items.some((i) => i.incluir)}
                className="w-full rounded-xl py-2.5 text-sm font-bold disabled:opacity-60"
                style={{ background: marca, color: txtMarca }}
              >
                {guardando ? 'Registrando...' : `Registrar ${items.filter((i) => i.incluir).length} compra(s)`}
              </button>
            </>
          )}
        </div>
      </div>
    </>
  );
}
