import type { Restaurante, DiaSemana } from './rows';

// Orden alineado con Date.getDay() y con extract(dow) de Postgres: 0=domingo.
const ORDEN: DiaSemana[] = ['dom', 'lun', 'mar', 'mie', 'jue', 'vie', 'sab'];

const NOMBRE: Record<DiaSemana, string> = {
  dom: 'domingo',
  lun: 'lunes',
  mar: 'martes',
  mie: 'miércoles',
  jue: 'jueves',
  vie: 'viernes',
  sab: 'sábado',
};

function aMinutos(hhmm: string): number | null {
  const m = /^(\d{1,2}):(\d{2})$/.exec(hhmm.trim());
  if (!m) return null;
  const h = +m[1];
  const mm = +m[2];
  if (h > 23 || mm > 59) return null;
  return h * 60 + mm;
}

// "17:00" -> "5:00 p. m."
export function hora12(hhmm: string): string {
  const min = aMinutos(hhmm);
  if (min == null) return hhmm;
  const h = Math.floor(min / 60);
  const mm = min % 60;
  const ap = h < 12 ? 'a. m.' : 'p. m.';
  const h12 = h % 12 === 0 ? 12 : h % 12;
  return `${h12}:${String(mm).padStart(2, '0')} ${ap}`;
}

// Dia (0=dom) y minutos del dia, en la hora de Venezuela.
function ahoraVE(ahora: Date): { dia: number; min: number } {
  const partes = new Intl.DateTimeFormat('en-US', {
    timeZone: 'America/Caracas',
    weekday: 'short',
    hour: '2-digit',
    minute: '2-digit',
    hourCycle: 'h23',
  }).formatToParts(ahora);
  const v = (t: string) => partes.find((p) => p.type === t)?.value ?? '';
  const map: Record<string, number> = { Sun: 0, Mon: 1, Tue: 2, Wed: 3, Thu: 4, Fri: 5, Sat: 6 };
  const dia = map[v('weekday')] ?? 0;
  const min = Number(v('hour')) * 60 + Number(v('minute'));
  return { dia, min };
}

export interface EstadoTienda {
  abierto: boolean;
  etiqueta: string; // 'Abierto' | 'Cerrado'
  detalle: string | null; // 'Abre hoy a las 5:00 p. m.' | 'Cierra a las 2:00 a. m.'
}

/**
 * Calcula si la tienda esta abierta AHORA combinando el switch manual (`abierto`)
 * con los `horarios` configurados. Soporta ventanas que cruzan la medianoche
 * (ej. abre 17:00, cierra 02:00). Si no hay horarios, se rige solo por el switch.
 */
export function estadoTienda(
  rest: Pick<Restaurante, 'abierto' | 'horarios'>,
  ahora: Date = new Date(),
): EstadoTienda {
  const h = rest.horarios;
  const tieneHorario = !!h && ORDEN.some((d) => h[d]?.activo);

  // Sin horarios: manda el switch manual.
  if (!tieneHorario) {
    return rest.abierto
      ? { abierto: true, etiqueta: 'Abierto', detalle: null }
      : { abierto: false, etiqueta: 'Cerrado', detalle: null };
  }

  const { dia, min } = ahoraVE(ahora);
  const cfgHoy = h![ORDEN[dia]];
  const cfgAyer = h![ORDEN[(dia + 6) % 7]];

  let dentro = false;
  let cierra: string | null = null;

  // Ventana de hoy.
  if (cfgHoy?.activo && cfgHoy.abre && cfgHoy.cierra) {
    const a = aMinutos(cfgHoy.abre);
    const c = aMinutos(cfgHoy.cierra);
    if (a != null && c != null) {
      if (c > a) {
        if (min >= a && min < c) {
          dentro = true;
          cierra = cfgHoy.cierra;
        }
      } else if (min >= a) {
        // cruza medianoche: abierta desde la apertura hasta las 24:00 (el resto es "manana")
        dentro = true;
        cierra = cfgHoy.cierra;
      }
    }
  }
  // Cola de la ventana de ayer que cruzo la medianoche.
  if (!dentro && cfgAyer?.activo && cfgAyer.abre && cfgAyer.cierra) {
    const a = aMinutos(cfgAyer.abre);
    const c = aMinutos(cfgAyer.cierra);
    if (a != null && c != null && c <= a && min < c) {
      dentro = true;
      cierra = cfgAyer.cierra;
    }
  }

  const abierto = rest.abierto && dentro;
  if (abierto) {
    return {
      abierto: true,
      etiqueta: 'Abierto',
      detalle: cierra ? `Cierra a las ${hora12(cierra)}` : null,
    };
  }

  // Cerrado a mano por el dueno.
  if (!rest.abierto) {
    return { abierto: false, etiqueta: 'Cerrado', detalle: 'Cerrado temporalmente' };
  }

  // Cerrado por horario: proxima apertura.
  for (let off = 0; off < 8; off++) {
    const key = ORDEN[(dia + off) % 7];
    const c = h![key];
    if (!c?.activo || !c.abre) continue;
    const a = aMinutos(c.abre);
    if (a == null) continue;
    if (off === 0 && min >= a) continue; // hoy ya abrio y ya paso
    const cuando = off === 0 ? 'hoy' : off === 1 ? 'mañana' : `el ${NOMBRE[key]}`;
    return { abierto: false, etiqueta: 'Cerrado', detalle: `Abre ${cuando} a las ${hora12(c.abre)}` };
  }
  return { abierto: false, etiqueta: 'Cerrado', detalle: null };
}
