/**
 * Cron diario 8:30 AM (America/Mexico_City) que envía emails de:
 *   - Alertas fiscales nuevas (Option B — una sola vez por alerta).
 *   - Recordatorios próximos a vencer en ventanas 3d / 1d / 0d.
 *
 * Por-tenant try/catch: un fallo en un tenant no bloquea al resto.
 */
import cron from 'node-cron';
import { prisma, tenantDb } from '../config/database.js';
import { processNewAlertas, processProximosRecordatorios } from '../services/notifications.service.js';

const SCHEDULE = '30 8 * * *'; // 08:30 AM diario

let task: ReturnType<typeof cron.schedule> | null = null;

/** Ejecuta ambos procesos para UN tenant. Exportado para disparo manual. */
export async function runNotificationsForTenant(tenantId: string): Promise<{
  alertasNuevas: number;
  recordatoriosEnviados: number;
}> {
  const tenant = await prisma.tenant.findUnique({
    where: { id: tenantId },
    select: { id: true, nombre: true, rfc: true, active: true, databaseName: true },
  });
  if (!tenant || !tenant.active) {
    return { alertasNuevas: 0, recordatoriosEnviados: 0 };
  }

  const pool = await tenantDb.getPool(tenantId, tenant.databaseName);
  const ctx = { rfc: tenant.rfc, nombre: tenant.nombre };

  const [alertasResult, recordResult] = await Promise.all([
    processNewAlertas(pool, tenantId, ctx).catch(err => {
      console.error(`[Notifications] Alertas (${tenant.rfc}) fallo:`, err.message || err);
      return { contribuyentes: 0, nuevasTotal: 0 };
    }),
    processProximosRecordatorios(pool, tenantId, ctx).catch(err => {
      console.error(`[Notifications] Recordatorios (${tenant.rfc}) fallo:`, err.message || err);
      return { enviados: 0 };
    }),
  ]);

  if (alertasResult.nuevasTotal > 0 || recordResult.enviados > 0) {
    console.log(`[Notifications] ${tenant.rfc}: ${alertasResult.nuevasTotal} alertas nuevas, ${recordResult.enviados} recordatorios`);
  }

  return {
    alertasNuevas: alertasResult.nuevasTotal,
    recordatoriosEnviados: recordResult.enviados,
  };
}

/** Itera todos los tenants activos. */
export async function runNotifications(): Promise<{
  tenants: number;
  alertasNuevas: number;
  recordatoriosEnviados: number;
}> {
  const tenants = await prisma.tenant.findMany({
    where: { active: true },
    select: { id: true, rfc: true },
  });

  let alertasNuevas = 0;
  let recordatoriosEnviados = 0;
  for (const t of tenants) {
    try {
      const r = await runNotificationsForTenant(t.id);
      alertasNuevas += r.alertasNuevas;
      recordatoriosEnviados += r.recordatoriosEnviados;
    } catch (err: any) {
      console.error(`[Notifications] Tenant ${t.rfc} fallo completo:`, err.message || err);
    }
  }
  return { tenants: tenants.length, alertasNuevas, recordatoriosEnviados };
}

export function startNotificationsJob(): void {
  if (task) {
    console.warn('[Notifications Cron] Ya iniciado');
    return;
  }
  task = cron.schedule(SCHEDULE, async () => {
    try {
      const result = await runNotifications();
      console.log(
        `[Notifications Cron] ${result.tenants} tenants — ` +
        `${result.alertasNuevas} alertas nuevas, ${result.recordatoriosEnviados} recordatorios`,
      );
    } catch (err: any) {
      console.error('[Notifications Cron] Error general:', err.message || err);
    }
  }, {
    timezone: 'America/Mexico_City',
  });
  console.log(`[Notifications Cron] Programado: ${SCHEDULE} (08:30 AM diario America/Mexico_City)`);
}

export function stopNotificationsJob(): void {
  if (task) {
    task.stop();
    task = null;
  }
}
