/**
 * APController - Controlador de Cuentas por Pagar
 *
 * Endpoints para cuentas por pagar y pagos a proveedores.
 *
 * @module Finance
 */

import { Router, Request, Response } from 'express';
import { DataSource } from 'typeorm';
import { APService } from '../services';

export function createAPController(dataSource: DataSource): Router {
  const router = Router();
  const service = new APService(dataSource);

  // ==================== CUENTAS POR PAGAR ====================

  /**
   * GET /
   * Lista cuentas por pagar con filtros
   */
  router.get('/', async (req: Request, res: Response) => {
    try {
      const ctx = {
        tenantId: req.headers['x-tenant-id'] as string,
        userId: (req as any).user?.id,
      };

      const options = {
        page: parseInt(req.query.page as string) || 1,
        limit: parseInt(req.query.limit as string) || 20,
        status: req.query.status as any,
        partnerId: req.query.partnerId as string,
        projectId: req.query.projectId as string,
        startDate: req.query.startDate ? new Date(req.query.startDate as string) : undefined,
        endDate: req.query.endDate ? new Date(req.query.endDate as string) : undefined,
        overdue: req.query.overdue === 'true',
        search: req.query.search as string,
      };

      const result = await service.findAll(ctx, options);
      res.json(result);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * GET /dashboard
   * Obtiene estadísticas del dashboard
   */
  router.get('/dashboard', async (req: Request, res: Response) => {
    try {
      const ctx = {
        tenantId: req.headers['x-tenant-id'] as string,
        userId: (req as any).user?.id,
      };

      const stats = await service.getDashboardStats(ctx);
      res.json(stats);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * GET /aging
   * Obtiene reporte de antigüedad
   */
  router.get('/aging', async (req: Request, res: Response) => {
    try {
      const ctx = {
        tenantId: req.headers['x-tenant-id'] as string,
        userId: (req as any).user?.id,
      };

      const options = {
        partnerId: req.query.partnerId as string,
        projectId: req.query.projectId as string,
        asOfDate: req.query.asOfDate ? new Date(req.query.asOfDate as string) : undefined,
      };

      const report = await service.getAgingReport(ctx, options);
      res.json(report);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * GET /payment-schedule
   * Obtiene calendario de pagos
   */
  router.get('/payment-schedule', async (req: Request, res: Response): Promise<void> => {
    try {
      const ctx = {
        tenantId: req.headers['x-tenant-id'] as string,
        userId: (req as any).user?.id,
      };

      const startDate = new Date(req.query.startDate as string);
      const endDate = new Date(req.query.endDate as string);

      if (isNaN(startDate.getTime()) || isNaN(endDate.getTime())) {
        res.status(400).json({ error: 'Fechas inválidas' });
        return;
      }

      const options = {
        partnerId: req.query.partnerId as string,
        projectId: req.query.projectId as string,
      };

      const schedule = await service.getPaymentSchedule(ctx, startDate, endDate, options);
      res.json(schedule);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * GET /:id
   * Obtiene una cuenta por pagar por ID
   */
  router.get('/:id', async (req: Request, res: Response): Promise<void> => {
    try {
      const ctx = {
        tenantId: req.headers['x-tenant-id'] as string,
        userId: (req as any).user?.id,
      };

      const ap = await service.findById(ctx, req.params.id);
      if (!ap) {
        res.status(404).json({ error: 'Cuenta por pagar no encontrada' });
        return;
      }

      res.json(ap);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * POST /
   * Crea una nueva cuenta por pagar
   */
  router.post('/', async (req: Request, res: Response) => {
    try {
      const ctx = {
        tenantId: req.headers['x-tenant-id'] as string,
        userId: (req as any).user?.id,
      };

      const ap = await service.create(ctx, req.body);
      res.status(201).json(ap);
    } catch (error) {
      res.status(400).json({ error: (error as Error).message });
    }
  });

  /**
   * PUT /:id
   * Actualiza una cuenta por pagar
   */
  router.put('/:id', async (req: Request, res: Response) => {
    try {
      const ctx = {
        tenantId: req.headers['x-tenant-id'] as string,
        userId: (req as any).user?.id,
      };

      const ap = await service.update(ctx, req.params.id, req.body);
      res.json(ap);
    } catch (error) {
      res.status(400).json({ error: (error as Error).message });
    }
  });

  /**
   * POST /:id/cancel
   * Cancela una cuenta por pagar
   */
  router.post('/:id/cancel', async (req: Request, res: Response): Promise<void> => {
    try {
      const ctx = {
        tenantId: req.headers['x-tenant-id'] as string,
        userId: (req as any).user?.id,
      };

      const { reason } = req.body;
      if (!reason) {
        res.status(400).json({ error: 'Se requiere motivo de cancelación' });
        return;
      }

      const ap = await service.cancel(ctx, req.params.id, reason);
      res.json(ap);
    } catch (error) {
      res.status(400).json({ error: (error as Error).message });
    }
  });

  // ==================== PAGOS ====================

  /**
   * POST /payments
   * Registra un pago a proveedores
   */
  router.post('/payments', async (req: Request, res: Response) => {
    try {
      const ctx = {
        tenantId: req.headers['x-tenant-id'] as string,
        userId: (req as any).user?.id,
      };

      const payment = await service.createPayment(ctx, req.body);
      res.status(201).json(payment);
    } catch (error) {
      res.status(400).json({ error: (error as Error).message });
    }
  });

  /**
   * POST /payments/:id/confirm
   * Confirma un pago
   */
  router.post('/payments/:id/confirm', async (req: Request, res: Response) => {
    try {
      const ctx = {
        tenantId: req.headers['x-tenant-id'] as string,
        userId: (req as any).user?.id,
      };

      const payment = await service.confirmPayment(ctx, req.params.id);
      res.json(payment);
    } catch (error) {
      res.status(400).json({ error: (error as Error).message });
    }
  });

  /**
   * POST /payments/:id/cancel
   * Cancela un pago
   */
  router.post('/payments/:id/cancel', async (req: Request, res: Response): Promise<void> => {
    try {
      const ctx = {
        tenantId: req.headers['x-tenant-id'] as string,
        userId: (req as any).user?.id,
      };

      const { reason } = req.body;
      if (!reason) {
        res.status(400).json({ error: 'Se requiere motivo de cancelación' });
        return;
      }

      const payment = await service.cancelPayment(ctx, req.params.id, reason);
      res.json(payment);
    } catch (error) {
      res.status(400).json({ error: (error as Error).message });
    }
  });

  return router;
}
