/**
 * ToolLoanController - Controlador de Prestamos de Herramientas
 *
 * Endpoints para gestion de prestamos de herramientas entre obras/empleados.
 *
 * @module Assets (MAE-015)
 * @gap GAP-002
 */

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

export function createToolLoanController(dataSource: DataSource): Router {
  const router = Router();
  const service = new ToolLoanService(dataSource);

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

  /**
   * GET /
   * Lista prestamos 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 = {
        status: req.query.status as any,
        employeeId: req.query.employeeId as string,
        toolId: req.query.toolId as string,
        fraccionamientoOrigenId: req.query.fraccionamientoOrigenId as string,
        fraccionamientoDestinoId: req.query.fraccionamientoDestinoId as string,
        overdue: req.query.overdue === 'true',
        search: req.query.search as string,
      };

      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 prestamos
   */
  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 /active
   * Lista prestamos activos
   */
  router.get('/active', async (req: Request, res: Response): Promise<void> => {
    try {
      const tenantId = req.headers['x-tenant-id'] as string;
      const loans = await service.getActiveLoans(tenantId);
      res.json(loans);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * GET /overdue
   * Lista prestamos vencidos
   */
  router.get('/overdue', async (req: Request, res: Response): Promise<void> => {
    try {
      const tenantId = req.headers['x-tenant-id'] as string;
      const loans = await service.getOverdueLoans(tenantId);
      res.json(loans);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * GET /by-employee/:employeeId
   * Prestamos por empleado
   */
  router.get('/by-employee/:employeeId', async (req: Request, res: Response): Promise<void> => {
    try {
      const tenantId = req.headers['x-tenant-id'] as string;
      const { employeeId } = req.params;
      const loans = await service.getLoansByEmployee(tenantId, employeeId);
      res.json(loans);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * GET /by-tool/:toolId
   * Historial de prestamos por herramienta
   */
  router.get('/by-tool/:toolId', async (req: Request, res: Response): Promise<void> => {
    try {
      const tenantId = req.headers['x-tenant-id'] as string;
      const { toolId } = req.params;
      const loans = await service.getLoansByTool(tenantId, toolId);
      res.json(loans);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * GET /:id
   * Obtiene prestamo 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 loan = await service.findById(tenantId, id);
      if (!loan) {
        res.status(404).json({ error: 'Prestamo no encontrado' });
        return;
      }
      res.json(loan);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * POST /
   * Crea un nuevo prestamo
   */
  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 loan = await service.create(tenantId, req.body, userId);
      res.status(201).json(loan);
    } catch (error) {
      res.status(400).json({ error: (error as Error).message });
    }
  });

  /**
   * PUT /:id
   * Actualiza un prestamo
   */
  router.put('/:id', 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 loan = await service.update(tenantId, id, req.body, userId);
      if (!loan) {
        res.status(404).json({ error: 'Prestamo no encontrado' });
        return;
      }
      res.json(loan);
    } catch (error) {
      res.status(400).json({ error: (error as Error).message });
    }
  });

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

  /**
   * POST /:id/return
   * Registra devolucion de herramienta
   */
  router.post('/:id/return', 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 loan = await service.returnTool(tenantId, id, req.body, userId);
      if (!loan) {
        res.status(404).json({ error: 'Prestamo no encontrado' });
        return;
      }
      res.json(loan);
    } catch (error) {
      res.status(400).json({ error: (error as Error).message });
    }
  });

  /**
   * POST /:id/lost
   * Marca herramienta como perdida
   */
  router.post('/:id/lost', 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 loan = await service.markAsLost(tenantId, id, req.body.notes, userId);
      if (!loan) {
        res.status(404).json({ error: 'Prestamo no encontrado' });
        return;
      }
      res.json(loan);
    } catch (error) {
      res.status(400).json({ error: (error as Error).message });
    }
  });

  /**
   * POST /:id/approve
   * Aprueba un prestamo
   */
  router.post('/:id/approve', 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 loan = await service.approveLoan(tenantId, id, userId);
      if (!loan) {
        res.status(404).json({ error: 'Prestamo no encontrado' });
        return;
      }
      res.json(loan);
    } catch (error) {
      res.status(400).json({ error: (error as Error).message });
    }
  });

  return router;
}
