import type { Request, Response } from 'express';
import {
  startSync,
  getSyncStatus,
  getSyncHistory,
  retryJob,
} from '../services/sat/sat.service.js';
import { getJobInfo, runSatSyncJobManually } from '../jobs/sat-sync.job.js';
import type { StartSyncRequest } from '@horux/shared';
import { isGlobalAdmin } from '../utils/global-admin.js';

function effectiveTenantId(req: Request): string {
  return req.viewingTenantId || req.user!.tenantId;
}

/**
 * Inicia una sincronización manual
 */
export async function start(req: Request, res: Response): Promise<void> {
  try {
    const tenantId = effectiveTenantId(req);
    const { type, dateFrom, dateTo } = req.body as StartSyncRequest;
    const contribuyenteId = req.body.contribuyenteId as string | undefined;

    const jobId = await startSync(
      tenantId,
      type || 'daily',
      dateFrom ? new Date(dateFrom) : undefined,
      dateTo ? new Date(dateTo) : undefined,
      contribuyenteId || undefined
    );

    res.json({
      jobId,
      message: 'Sincronización iniciada',
    });
  } catch (error: any) {
    console.error('[SAT Controller] Error en start:', error);

    if (error.message.includes('FIEL') || error.message.includes('sincronización en curso')) {
      res.status(400).json({ error: error.message });
      return;
    }

    res.status(500).json({ error: 'Error interno del servidor' });
  }
}

/**
 * Obtiene el estado actual de sincronización
 */
export async function status(req: Request, res: Response): Promise<void> {
  try {
    const tenantId = effectiveTenantId(req);
    const contribuyenteId = req.query.contribuyenteId as string | undefined;
    const syncStatus = await getSyncStatus(tenantId, contribuyenteId || undefined);
    res.json(syncStatus);
  } catch (error: any) {
    console.error('[SAT Controller] Error en status:', error);
    res.status(500).json({ error: 'Error interno del servidor' });
  }
}

/**
 * Obtiene el historial de sincronizaciones
 */
export async function history(req: Request, res: Response): Promise<void> {
  try {
    const tenantId = effectiveTenantId(req);
    const page = parseInt(req.query.page as string) || 1;
    const limit = parseInt(req.query.limit as string) || 10;
    const contribuyenteId = req.query.contribuyenteId as string | undefined;

    const result = await getSyncHistory(tenantId, page, limit, contribuyenteId || undefined);
    res.json({
      ...result,
      page,
      limit,
    });
  } catch (error: any) {
    console.error('[SAT Controller] Error en history:', error);
    res.status(500).json({ error: 'Error interno del servidor' });
  }
}

/**
 * Obtiene detalle de un job específico
 */
export async function jobDetail(req: Request, res: Response): Promise<void> {
  try {
    const tenantId = effectiveTenantId(req);
    const { id } = req.params;
    const { jobs } = await getSyncHistory(tenantId, 1, 100);
    const job = jobs.find(j => j.id === id);

    if (!job) {
      res.status(404).json({ error: 'Job no encontrado' });
      return;
    }

    res.json(job);
  } catch (error: any) {
    console.error('[SAT Controller] Error en jobDetail:', error);
    res.status(500).json({ error: 'Error interno del servidor' });
  }
}

/**
 * Reintenta un job fallido
 */
export async function retry(req: Request, res: Response): Promise<void> {
  try {
    const id = req.params.id as string;
    const newJobId = await retryJob(id);

    res.json({
      jobId: newJobId,
      message: 'Job reintentado',
    });
  } catch (error: any) {
    console.error('[SAT Controller] Error en retry:', error);

    if (error.message.includes('no encontrado') || error.message.includes('Solo se pueden')) {
      res.status(400).json({ error: error.message });
      return;
    }

    res.status(500).json({ error: 'Error interno del servidor' });
  }
}

/**
 * Obtiene información del job programado (solo admin global)
 */
export async function cronInfo(req: Request, res: Response): Promise<void> {
  try {
    if (!(await isGlobalAdmin(req.user!.tenantId, req.user!.role))) {
      res.status(403).json({ error: 'Solo el administrador global puede ver info del cron' });
      return;
    }
    const info = getJobInfo();
    res.json(info);
  } catch (error: any) {
    console.error('[SAT Controller] Error en cronInfo:', error);
    res.status(500).json({ error: 'Error interno del servidor' });
  }
}

/**
 * Ejecuta el job de sincronización manualmente (solo admin global)
 */
export async function runCron(req: Request, res: Response): Promise<void> {
  try {
    if (!(await isGlobalAdmin(req.user!.tenantId, req.user!.role))) {
      res.status(403).json({ error: 'Solo el administrador global puede ejecutar el cron' });
      return;
    }
    // Ejecutar en background
    runSatSyncJobManually().catch(err =>
      console.error('[SAT Controller] Error ejecutando cron manual:', err)
    );

    res.json({ message: 'Job de sincronización iniciado' });
  } catch (error: any) {
    console.error('[SAT Controller] Error en runCron:', error);
    res.status(500).json({ error: 'Error interno del servidor' });
  }
}
