/**
 * Estado del período de prueba de un add-on.
 *
 * El estado NO se persiste: se deriva de `fecha_fin_prueba` contra la fecha de
 * hoy. Guardarlo obligaría a un job que mueva estados y que, el día que no
 * corra, deja empresas en un estado que no es el real.
 *
 * Línea de tiempo:
 *
 *   |<------- prueba ------->|<--- solo_lectura (30 d) --->|  bloqueado
 *                            ^
 *                      fecha_fin_prueba
 *
 * `activo` es el caso normal: la empresa contrató el add-on y no hay prueba
 * corriendo (`fecha_fin_prueba IS NULL`). Es el estado de todas las empresas
 * hoy, así que el comportamiento no cambia para nadie hasta que alguien
 * arranque una prueba.
 */
export type EstadoPrueba = 'activo' | 'prueba' | 'solo_lectura' | 'bloqueado';

/** Días de solo lectura tras vencer la prueba. Los datos se conservan (spec §12). */
export const DIAS_GRACIA_PRUEBA = 30;

/** Compara sólo la parte de fecha: la prueba vence al final del día, no a la hora exacta. */
function aDia(fecha: Date): number {
  return Date.UTC(fecha.getUTCFullYear(), fecha.getUTCMonth(), fecha.getUTCDate());
}

export function estadoPrueba(
  fechaFinPrueba: Date | null | undefined,
  hoy: Date = new Date(),
  diasGracia: number = DIAS_GRACIA_PRUEBA,
): EstadoPrueba {
  if (!fechaFinPrueba) return 'activo';

  const fin = aDia(fechaFinPrueba);
  const dia = aDia(hoy);
  if (dia <= fin) return 'prueba';

  const finGracia = fin + diasGracia * 86_400_000;
  return dia <= finGracia ? 'solo_lectura' : 'bloqueado';
}

/** Días que faltan para que termine la prueba. Negativo = ya venció. */
export function diasRestantesPrueba(fechaFinPrueba: Date | null | undefined, hoy: Date = new Date()): number | null {
  if (!fechaFinPrueba) return null;
  return Math.round((aDia(fechaFinPrueba) - aDia(hoy)) / 86_400_000);
}

/** En solo_lectura sólo pasan los métodos que no modifican nada. */
export function metodoEsLectura(metodo: string): boolean {
  return ['GET', 'HEAD', 'OPTIONS'].includes(metodo.toUpperCase());
}
