/**
 * ChangeLogController - Controlador de Historial de Cambios
 *
 * Endpoints para consultar el registro de cambios de auditoria.
 *
 * @module Admin
 * @gap GAP-007
 */

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

export function createChangeLogController(dataSource: DataSource): Router {
  const router = Router();
  const service = new ChangeLogService(dataSource);

  // ==================== QUERIES ====================

  /**
   * GET /
   * Lista cambios 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 = {
        tableSchema: req.query.tableSchema as string,
        tableName: req.query.tableName as string,
        recordId: req.query.recordId as string,
        userId: req.query.userId as string,
        operation: req.query.operation 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) || 50,
      };

      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 cambios
   */
  router.get('/statistics', async (req: Request, res: Response): Promise<void> => {
    try {
      const tenantId = req.headers['x-tenant-id'] as string;
      const fromDate = req.query.fromDate ? new Date(req.query.fromDate as string) : undefined;
      const toDate = req.query.toDate ? new Date(req.query.toDate as string) : undefined;

      const stats = await service.getStatistics(tenantId, fromDate, toDate);
      res.json(stats);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * GET /recent
   * Cambios recientes
   */
  router.get('/recent', async (req: Request, res: Response): Promise<void> => {
    try {
      const tenantId = req.headers['x-tenant-id'] as string;
      const hours = parseInt(req.query.hours as string) || 24;
      const limit = parseInt(req.query.limit as string) || 100;

      const changes = await service.getRecentChanges(tenantId, hours, limit);
      res.json(changes);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

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

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

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

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

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

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

  /**
   * GET /history/:schema/:table/:recordId
   * Historial completo de un registro
   */
  router.get('/history/:schema/:table/:recordId', async (req: Request, res: Response): Promise<void> => {
    try {
      const tenantId = req.headers['x-tenant-id'] as string;
      const { schema, table, recordId } = req.params;
      const limit = parseInt(req.query.limit as string) || 100;

      const history = await service.getRecordHistory(tenantId, schema, table, recordId, limit);
      res.json(history);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * GET /:id
   * Obtiene cambio por ID
   */
  router.get('/:id', async (req: Request, res: Response): Promise<void> => {
    try {
      const { id } = req.params;

      const change = await service.findById(id);
      if (!change) {
        res.status(404).json({ error: 'Registro de cambio no encontrado' });
        return;
      }
      res.json(change);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  // ==================== MANTENIMIENTO ====================

  /**
   * DELETE /purge
   * Purgar registros antiguos (admin only)
   */
  router.delete('/purge', async (req: Request, res: Response): Promise<void> => {
    try {
      const tenantId = req.headers['x-tenant-id'] as string;
      const daysToKeep = parseInt(req.query.daysToKeep as string) || 90;

      const deleted = await service.purgeOldRecords(tenantId, daysToKeep);
      res.json({ deleted });
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  return router;
}
