// ESPEJO LOCAL: la copia del menu del negocio que vive en la laptop, para que
// el salon funcione SIN internet. Se refresca desde la nube cuando la hay y se
// guarda en disco (local/espejo.json) para sobrevivir reinicios y apagones.
import { mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs';
import { join } from 'node:path';
import type { SupabaseClient } from '@supabase/supabase-js';
import type { Puesto } from './tipos.js';

export interface EspejoCategoria {
  id: string;
  nombre: string;
  orden: number;
  a_cocina: boolean | null;
  puesto_id: string | null;
}

export interface EspejoProducto {
  id: string;
  nombre: string;
  precio_usd: number;
  categoria_id: string | null;
  puesto_id: string | null;
  disponible: boolean;
  opciones: unknown;
}

export interface Espejo {
  restaurante: { id: string; nombre: string; prefijo: string | null; num_mesas: number; tasa_bs: number | null };
  puestos: Puesto[];
  categorias: EspejoCategoria[];
  productos: EspejoProducto[];
  actualizado_en: string;
}

function rutaEspejo(base: string): string {
  return join(base, 'local', 'espejo.json');
}

/** Escritura atomica: primero a un temporal y despues rename (un apagon no deja el archivo a medias). */
export function escribirAtomico(ruta: string, contenido: string): void {
  const tmp = ruta + '.tmp';
  writeFileSync(tmp, contenido);
  renameSync(tmp, ruta);
}

export function cargarEspejo(base: string): Espejo | null {
  try {
    return JSON.parse(readFileSync(rutaEspejo(base), 'utf8')) as Espejo;
  } catch {
    return null;
  }
}

export function guardarEspejo(base: string, e: Espejo): void {
  mkdirSync(join(base, 'local'), { recursive: true });
  escribirAtomico(rutaEspejo(base), JSON.stringify(e));
}

/** Baja el espejo fresco desde la nube (requiere sesion del negocio ya abierta). */
export async function refrescarEspejo(
  supabase: SupabaseClient,
  restauranteId: string,
  base: string,
): Promise<Espejo> {
  const [rest, puestos, cats, prods] = await Promise.all([
    supabase.from('restaurantes').select('id,nombre,prefijo,num_mesas,tasa_bs').eq('id', restauranteId).maybeSingle(),
    supabase.from('puestos_impresion').select('id,nombre,orden,es_defecto,activo').eq('restaurante_id', restauranteId).order('orden'),
    supabase.from('categorias').select('id,nombre,orden,a_cocina,puesto_id').eq('restaurante_id', restauranteId).order('orden'),
    // Sin `archivado`, el POS de las tablets seguiria vendiendo platos que el
    // negocio ya saco de la carta (y con el precio viejo).
    supabase.from('productos').select('id,nombre,precio_usd,categoria_id,puesto_id,disponible,opciones').eq('restaurante_id', restauranteId).eq('archivado', false).order('orden'),
  ]);
  const error = rest.error ?? puestos.error ?? cats.error ?? prods.error;
  if (error || !rest.data) throw new Error('espejo: ' + (error?.message ?? 'restaurante no legible'));
  const e: Espejo = {
    restaurante: rest.data as Espejo['restaurante'],
    puestos: (puestos.data ?? []) as Espejo['puestos'],
    categorias: (cats.data ?? []) as EspejoCategoria[],
    productos: (prods.data ?? []) as EspejoProducto[],
    actualizado_en: new Date().toISOString(),
  };
  guardarEspejo(base, e);
  return e;
}
