// Edge Function: cerebro-factura (Cerebro de costos, fase 1)
// Recibe la FOTO de una factura/recibo/cuaderno de compras y usa Gemini (vision)
// para extraer los renglones: descripcion, cantidad convertida a unidad base
// (g/ml/unidad), costo total y moneda. Matchea contra los ingredientes que ya
// tiene el negocio; lo nuevo viene con nombre normalizado para crearlo.
// La conversion Bs->USD NO la hace la IA: la hace el panel con la tasa vigente.
// Mismo molde de importar-menu-ia: sesion validada con los endpoints internos,
// la API key vive solo en el servidor.

const CORS = {
  'Access-Control-Allow-Origin': '*',
  'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
  'Access-Control-Allow-Methods': 'POST, OPTIONS',
};

function json(obj: unknown, status = 200) {
  return new Response(JSON.stringify(obj), {
    status,
    headers: { ...CORS, 'Content-Type': 'application/json' },
  });
}

Deno.serve(async (req) => {
  if (req.method === 'OPTIONS') return new Response('ok', { headers: CORS });
  if (req.method !== 'POST') return json({ error: 'Metodo no permitido' }, 405);

  try {
    const SUPABASE_URL = Deno.env.get('SUPABASE_URL')!;
    const ANON = Deno.env.get('SUPABASE_ANON_KEY')!;
    const authHeader = req.headers.get('Authorization');
    if (!authHeader) return json({ error: 'No autorizado' }, 401);

    const uRes = await fetch(`${SUPABASE_URL}/auth/v1/user`, {
      headers: { Authorization: authHeader, apikey: ANON },
    });
    if (!uRes.ok) return json({ error: 'Sesion invalida' }, 401);
    const user = (await uRes.json()) as { id?: string };
    if (!user?.id) return json({ error: 'Sesion invalida' }, 401);

    const pRes = await fetch(`${SUPABASE_URL}/rest/v1/perfiles?id=eq.${user.id}&select=rol`, {
      headers: { Authorization: authHeader, apikey: ANON },
    });
    const perfiles = pRes.ok ? ((await pRes.json()) as { rol?: string }[]) : [];
    const rol = perfiles?.[0]?.rol;
    if (!rol || !['dueno', 'encargado', 'admin'].includes(rol)) {
      return json({ error: 'Solo el dueno o el encargado registran compras' }, 403);
    }

    const { imagen_base64, mime_type, ingredientes } = (await req.json()) as {
      imagen_base64?: string;
      mime_type?: string;
      ingredientes?: { id: string; nombre: string; unidad_base: string }[];
    };
    if (!imagen_base64) return json({ error: 'Falta la imagen' }, 400);

    const KEY = Deno.env.get('GEMINI_API_KEY');
    if (!KEY) return json({ error: 'Falta configurar GEMINI_API_KEY en el servidor' }, 500);
    const MODEL = Deno.env.get('GEMINI_MODEL') ?? 'gemini-2.5-flash';

    const listaIng = (ingredientes ?? [])
      .map((i) => `- id=${i.id} | ${i.nombre} | unidad=${i.unidad_base}`)
      .join('\n');

    const PROMPT = `Eres el contador de cocina de un restaurante en VENEZUELA.
Analiza la imagen: es una factura, recibo, nota de entrega o cuaderno de compras de comida.
Extrae CADA renglon comprado y devuelve SOLO JSON valido con esta forma exacta:
{"items":[{"descripcion":"tal cual dice el papel","cantidad_base":0,"unidad_base":"g","costo_total":0,"moneda":"bs","ingrediente_id":null,"nombre_nuevo":"Nombre Normalizado"}]}
Reglas DURAS:
- "cantidad_base" es la cantidad TOTAL comprada CONVERTIDA a la unidad base: gramos para solidos (1 kg = 1000), mililitros para liquidos (1 L = 1000), "unidad" para cosas que se cuentan (huevos, empaques). "unidad_base" es "g", "ml" o "unidad".
- Si el renglon dice "2 sacos de 20kg", cantidad_base = 40000 y unidad_base = "g".
- "costo_total" es el costo TOTAL del renglon (no unitario) tal cual el papel. "moneda" es "bs" si esta en bolivares (lo normal en Venezuela) o "usd" si esta claramente en dolares ($, USD, REF). NO conviertas monedas.
- Ingredientes que YA existen en el negocio (matchea por nombre aunque este escrito distinto, ej "harina pan" = "Harina de maiz"):
${listaIng || '(ninguno todavia)'}
  Si el renglon corresponde a uno de ellos, pon su "ingrediente_id" y "nombre_nuevo" en null, y usa SU unidad base.
- Si no corresponde a ninguno, "ingrediente_id" null y "nombre_nuevo" con un nombre corto normalizado (ej "Queso blanco", "Harina de maiz").
- Ignora renglones que no son comida ni insumos de cocina (IVA, subtotales, telefonos).
- No inventes renglones que no esten en el papel.`;

    const body = {
      contents: [
        {
          parts: [
            { inline_data: { mime_type: mime_type ?? 'image/jpeg', data: imagen_base64 } },
            { text: PROMPT },
          ],
        },
      ],
      generationConfig: { responseMimeType: 'application/json' },
    };

    const r = await fetch(
      `https://generativelanguage.googleapis.com/v1beta/models/${MODEL}:generateContent`,
      {
        method: 'POST',
        headers: { 'x-goog-api-key': KEY, 'Content-Type': 'application/json' },
        body: JSON.stringify(body),
      },
    );
    if (!r.ok) {
      const t = await r.text();
      return json({ error: 'La IA no pudo leer la factura', detalle: t.slice(0, 200) }, 502);
    }
    const j = await r.json();
    const txt = j?.candidates?.[0]?.content?.parts?.[0]?.text;
    if (!txt) return json({ error: 'La IA no devolvio resultados' }, 502);

    let parsed: { items?: unknown };
    try {
      parsed = JSON.parse(txt);
    } catch {
      return json({ error: 'La IA devolvio un formato invalido' }, 502);
    }

    const idsValidos = new Set((ingredientes ?? []).map((i) => i.id));
    const items = (Array.isArray(parsed.items) ? parsed.items : [])
      .filter((x): x is Record<string, unknown> => !!x && typeof x === 'object')
      .map((x) => ({
        descripcion: typeof x.descripcion === 'string' ? x.descripcion.slice(0, 200) : '',
        cantidad_base: Number(x.cantidad_base) > 0 ? Number(x.cantidad_base) : 0,
        unidad_base: ['g', 'ml', 'unidad'].includes(String(x.unidad_base)) ? String(x.unidad_base) : 'g',
        costo_total: Number(x.costo_total) >= 0 ? Number(x.costo_total) : 0,
        moneda: x.moneda === 'usd' ? 'usd' : 'bs',
        ingrediente_id: typeof x.ingrediente_id === 'string' && idsValidos.has(x.ingrediente_id) ? x.ingrediente_id : null,
        nombre_nuevo: typeof x.nombre_nuevo === 'string' ? x.nombre_nuevo.slice(0, 80) : null,
      }))
      .filter((x) => x.cantidad_base > 0 && (x.ingrediente_id || x.nombre_nuevo));

    return json({ items });
  } catch (e) {
    return json({ error: 'Error inesperado: ' + (e as Error).message }, 500);
  }
});
