/**
 * DigitalSignatureController - Controlador de Firmas Digitales
 *
 * Endpoints para gestion de firmas digitales de documentos.
 *
 * @module Documents (MAE-016)
 * @gap GAP-006
 */

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

export function createDigitalSignatureController(dataSource: DataSource): Router {
  const router = Router();
  const service = new DigitalSignatureService(dataSource);

  // ==================== CRUD ====================

  /**
   * GET /
   * Lista firmas con filtros y paginacion
   */
  router.get('/', async (req: Request, res: Response, _next: NextFunction): Promise<void> => {
    try {
      const tenantId = req.headers['x-tenant-id'] as string;

      const filters = {
        documentId: req.query.documentId as string,
        signerId: req.query.signerId as string,
        status: req.query.status as any,
        signatureType: req.query.signatureType as any,
        fromDate: req.query.fromDate ? new Date(req.query.fromDate as string) : undefined,
        toDate: req.query.toDate ? new Date(req.query.toDate as string) : undefined,
      };

      const pagination = {
        page: parseInt(req.query.page as string) || 1,
        limit: parseInt(req.query.limit as string) || 20,
      };

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

  /**
   * GET /statistics
   * Estadisticas de firmas
   */
  router.get('/statistics', async (req: Request, res: Response): Promise<void> => {
    try {
      const tenantId = req.headers['x-tenant-id'] as string;
      const stats = await service.getStatistics(tenantId);
      res.json(stats);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * GET /pending
   * Lista firmas pendientes
   */
  router.get('/pending', async (req: Request, res: Response): Promise<void> => {
    try {
      const tenantId = req.headers['x-tenant-id'] as string;
      const signerId = req.query.signerId as string | undefined;
      const signatures = await service.getPendingSignatures(tenantId, signerId);
      res.json(signatures);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * GET /by-document/:documentId
   * Firmas de un documento
   */
  router.get('/by-document/:documentId', async (req: Request, res: Response): Promise<void> => {
    try {
      const tenantId = req.headers['x-tenant-id'] as string;
      const { documentId } = req.params;
      const signatures = await service.getByDocument(tenantId, documentId);
      res.json(signatures);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * GET /by-signer/:signerId
   * Firmas de un firmante
   */
  router.get('/by-signer/:signerId', async (req: Request, res: Response): Promise<void> => {
    try {
      const tenantId = req.headers['x-tenant-id'] as string;
      const { signerId } = req.params;
      const signatures = await service.getBySigner(tenantId, signerId);
      res.json(signatures);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * GET /:id
   * Obtiene firma por ID
   */
  router.get('/:id', async (req: Request, res: Response): Promise<void> => {
    try {
      const tenantId = req.headers['x-tenant-id'] as string;
      const { id } = req.params;

      const signature = await service.findById(tenantId, id);
      if (!signature) {
        res.status(404).json({ error: 'Firma no encontrada' });
        return;
      }
      res.json(signature);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * POST /
   * Solicita una nueva firma
   */
  router.post('/', async (req: Request, res: Response): Promise<void> => {
    try {
      const tenantId = req.headers['x-tenant-id'] as string;
      const userId = req.headers['x-user-id'] as string;

      const signature = await service.requestSignature(tenantId, req.body, userId);
      res.status(201).json(signature);
    } catch (error) {
      res.status(400).json({ error: (error as Error).message });
    }
  });

  // ==================== OPERACIONES ====================

  /**
   * POST /:id/sign
   * Firmar documento
   */
  router.post('/:id/sign', async (req: Request, res: Response): Promise<void> => {
    try {
      const tenantId = req.headers['x-tenant-id'] as string;
      const userId = req.headers['x-user-id'] as string;
      const { id } = req.params;

      // Agregar IP y User-Agent del request
      const dto = {
        ...req.body,
        ipAddress: req.ip || req.headers['x-forwarded-for'],
        userAgent: req.headers['user-agent'],
      };

      const signature = await service.signDocument(tenantId, id, dto, userId);
      if (!signature) {
        res.status(404).json({ error: 'Firma no encontrada' });
        return;
      }
      res.json(signature);
    } catch (error) {
      res.status(400).json({ error: (error as Error).message });
    }
  });

  /**
   * POST /:id/reject
   * Rechazar solicitud de firma
   */
  router.post('/:id/reject', async (req: Request, res: Response): Promise<void> => {
    try {
      const tenantId = req.headers['x-tenant-id'] as string;
      const userId = req.headers['x-user-id'] as string;
      const { id } = req.params;

      const signature = await service.rejectSignature(tenantId, id, req.body, userId);
      if (!signature) {
        res.status(404).json({ error: 'Firma no encontrada' });
        return;
      }
      res.json(signature);
    } catch (error) {
      res.status(400).json({ error: (error as Error).message });
    }
  });

  /**
   * POST /:id/revoke
   * Revocar firma
   */
  router.post('/:id/revoke', async (req: Request, res: Response): Promise<void> => {
    try {
      const tenantId = req.headers['x-tenant-id'] as string;
      const userId = req.headers['x-user-id'] as string;
      const { id } = req.params;

      const signature = await service.revokeSignature(tenantId, id, req.body.reason, userId);
      if (!signature) {
        res.status(404).json({ error: 'Firma no encontrada' });
        return;
      }
      res.json(signature);
    } catch (error) {
      res.status(400).json({ error: (error as Error).message });
    }
  });

  /**
   * POST /:id/validate
   * Validar firma
   */
  router.post('/:id/validate', async (req: Request, res: Response): Promise<void> => {
    try {
      const tenantId = req.headers['x-tenant-id'] as string;
      const { id } = req.params;

      const result = await service.validateSignature(tenantId, id);
      res.json(result);
    } catch (error) {
      res.status(400).json({ error: (error as Error).message });
    }
  });

  /**
   * POST /mark-expired
   * Marcar firmas expiradas (job interno)
   */
  router.post('/mark-expired', async (req: Request, res: Response): Promise<void> => {
    try {
      const tenantId = req.headers['x-tenant-id'] as string;
      const count = await service.markExpiredSignatures(tenantId);
      res.json({ marked: count });
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  return router;
}
