/**
 * DepreciationController - Controlador de Depreciacion
 *
 * Endpoints para gestion de depreciacion de activos fijos.
 *
 * @module Assets (MAE-015)
 * @gap GAP-003
 */

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

export function createDepreciationController(dataSource: DataSource): Router {
  const router = Router();
  const service = new DepreciationService(dataSource);

  // ==================== SCHEDULES ====================

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

      const filters = {
        assetType: req.query.assetType as any,
        method: req.query.method as any,
        isActive: req.query.isActive === 'true' ? true : req.query.isActive === 'false' ? false : undefined,
        isFullyDepreciated: req.query.isFullyDepreciated === 'true' ? true : req.query.isFullyDepreciated === 'false' ? false : undefined,
      };

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

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

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

  /**
   * GET /pending
   * Lista depreciaciones pendientes
   */
  router.get('/pending', async (req: Request, res: Response): Promise<void> => {
    try {
      const tenantId = req.headers['x-tenant-id'] as string;
      const asOfDate = req.query.asOfDate ? new Date(req.query.asOfDate as string) : new Date();
      const schedules = await service.getPendingDepreciations(tenantId, asOfDate);
      res.json(schedules);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * GET /schedules/by-asset/:assetId
   * Calendario de depreciacion por activo
   */
  router.get('/schedules/by-asset/:assetId', async (req: Request, res: Response): Promise<void> => {
    try {
      const tenantId = req.headers['x-tenant-id'] as string;
      const { assetId } = req.params;

      const schedule = await service.findScheduleByAsset(tenantId, assetId);
      if (!schedule) {
        res.status(404).json({ error: 'Calendario de depreciacion no encontrado' });
        return;
      }
      res.json(schedule);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

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

      const schedule = await service.findScheduleById(tenantId, id);
      if (!schedule) {
        res.status(404).json({ error: 'Calendario de depreciacion no encontrado' });
        return;
      }
      res.json(schedule);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * POST /schedules
   * Crea un nuevo calendario de depreciacion
   */
  router.post('/schedules', 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 schedule = await service.createSchedule(tenantId, req.body, userId);
      res.status(201).json(schedule);
    } catch (error) {
      res.status(400).json({ error: (error as Error).message });
    }
  });

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

  // ==================== ENTRIES ====================

  /**
   * GET /schedules/:scheduleId/entries
   * Lista entradas de depreciacion por calendario
   */
  router.get('/schedules/:scheduleId/entries', async (req: Request, res: Response): Promise<void> => {
    try {
      const tenantId = req.headers['x-tenant-id'] as string;
      const { scheduleId } = req.params;

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

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

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

      const entry = await service.findEntryById(tenantId, id);
      if (!entry) {
        res.status(404).json({ error: 'Entrada de depreciacion no encontrada' });
        return;
      }
      res.json(entry);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * POST /entries
   * Crea una entrada de depreciacion manual
   */
  router.post('/entries', 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 entry = await service.createEntry(tenantId, req.body, userId);
      res.status(201).json(entry);
    } catch (error) {
      res.status(400).json({ error: (error as Error).message });
    }
  });

  /**
   * POST /schedules/:scheduleId/generate-entry
   * Genera entrada de depreciacion mensual automatica
   */
  router.post('/schedules/:scheduleId/generate-entry', 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 { scheduleId } = req.params;
      const { periodDate, unitsUsed } = req.body;

      const entry = await service.generateMonthlyEntry(
        tenantId,
        scheduleId,
        new Date(periodDate),
        unitsUsed,
        userId
      );
      res.status(201).json(entry);
    } catch (error) {
      res.status(400).json({ error: (error as Error).message });
    }
  });

  /**
   * POST /entries/:id/post
   * Contabiliza una entrada de depreciacion
   */
  router.post('/entries/:id/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 { id } = req.params;
      const { journalEntryId } = req.body;

      const entry = await service.postEntry(tenantId, id, journalEntryId, userId);
      if (!entry) {
        res.status(404).json({ error: 'Entrada de depreciacion no encontrada' });
        return;
      }
      res.json(entry);
    } catch (error) {
      res.status(400).json({ error: (error as Error).message });
    }
  });

  return router;
}
