/**
 * SegmentoRuta Controller
 * ERP Transportistas
 *
 * REST API endpoints for route segment management.
 * Adapted from erp-mecanicas-diesel MMD-014 GPS Integration
 * Module: MAI-006 Tracking
 */

import { Router, Request, Response, NextFunction } from 'express';
import { DataSource } from 'typeorm';
import { SegmentoRutaService, SegmentoRutaFilters } from '../services/segmento-ruta.service';
import { TipoSegmento } from '../entities/segmento-ruta.entity';

interface TenantRequest extends Request {
  tenantId?: string;
  userId?: string;
}

export function createSegmentoRutaController(dataSource: DataSource): Router {
  const router = Router();
  const service = new SegmentoRutaService(dataSource);

  const extractTenant = (req: TenantRequest, res: Response, next: NextFunction) => {
    const tenantId = req.headers['x-tenant-id'] as string;
    if (!tenantId) {
      return res.status(400).json({ error: 'Tenant ID es requerido' });
    }
    req.tenantId = tenantId;
    req.userId = req.headers['x-user-id'] as string;
    next();
  };

  router.use(extractTenant);

  /**
   * Create a route segment
   * POST /api/gps/segmentos
   */
  router.post('/', async (req: TenantRequest, res: Response) => {
    try {
      const segmento = await service.create(req.tenantId!, {
        ...req.body,
        tiempoInicio: new Date(req.body.tiempoInicio),
        tiempoFin: new Date(req.body.tiempoFin),
      });
      res.status(201).json(segmento);
    } catch (error) {
      res.status(400).json({ error: (error as Error).message });
    }
  });

  /**
   * Calculate route segment from positions
   * POST /api/gps/segmentos/calcular
   */
  router.post('/calcular', async (req: TenantRequest, res: Response) => {
    try {
      const { dispositivoId, tiempoInicio, tiempoFin, viajeId, tipoSegmento } = req.body;
      const segmento = await service.calcularRutaDesdePosiciones(
        req.tenantId!,
        dispositivoId,
        new Date(tiempoInicio),
        new Date(tiempoFin),
        viajeId,
        tipoSegmento as TipoSegmento
      );

      if (!segmento) {
        return res.status(400).json({ error: 'No hay suficientes posiciones para calcular el segmento' });
      }
      res.status(201).json(segmento);
    } catch (error) {
      res.status(400).json({ error: (error as Error).message });
    }
  });

  /**
   * List route segments with filters
   * GET /api/gps/segmentos
   */
  router.get('/', async (req: TenantRequest, res: Response) => {
    try {
      const filters: SegmentoRutaFilters = {
        viajeId: req.query.viajeId as string,
        unidadId: req.query.unidadId as string,
        dispositivoId: req.query.dispositivoId as string,
        tipoSegmento: req.query.tipoSegmento as TipoSegmento,
        esValido: req.query.esValido === 'true' ? true : req.query.esValido === 'false' ? false : undefined,
        fechaInicio: req.query.fechaInicio ? new Date(req.query.fechaInicio as string) : undefined,
        fechaFin: req.query.fechaFin ? new Date(req.query.fechaFin as string) : undefined,
      };

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

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

  /**
   * Get route summary for a viaje
   * GET /api/gps/segmentos/viaje/:viajeId/resumen
   */
  router.get('/viaje/:viajeId/resumen', async (req: TenantRequest, res: Response) => {
    try {
      const resumen = await service.getResumenRutaViaje(req.tenantId!, req.params.viajeId);
      if (!resumen) {
        return res.status(404).json({ error: 'No hay segmentos para el viaje' });
      }
      res.json(resumen);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * Get segments for a viaje
   * GET /api/gps/segmentos/viaje/:viajeId
   */
  router.get('/viaje/:viajeId', async (req: TenantRequest, res: Response) => {
    try {
      const segmentos = await service.findByViaje(req.tenantId!, req.params.viajeId);
      res.json(segmentos);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * Get statistics for a unit
   * GET /api/gps/segmentos/unidad/:unidadId/estadisticas
   */
  router.get('/unidad/:unidadId/estadisticas', async (req: TenantRequest, res: Response) => {
    try {
      const fechaInicio = req.query.fechaInicio ? new Date(req.query.fechaInicio as string) : undefined;
      const fechaFin = req.query.fechaFin ? new Date(req.query.fechaFin as string) : undefined;

      const estadisticas = await service.getEstadisticasUnidad(
        req.tenantId!,
        req.params.unidadId,
        fechaInicio,
        fechaFin
      );
      res.json(estadisticas);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * Get segment by ID
   * GET /api/gps/segmentos/:id
   */
  router.get('/:id', async (req: TenantRequest, res: Response) => {
    try {
      const segmento = await service.findById(req.tenantId!, req.params.id);
      if (!segmento) {
        return res.status(404).json({ error: 'Segmento no encontrado' });
      }
      res.json(segmento);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * Update segment validity
   * PATCH /api/gps/segmentos/:id/validez
   */
  router.patch('/:id/validez', async (req: TenantRequest, res: Response) => {
    try {
      const { esValido, notas } = req.body;
      const segmento = await service.updateValidez(req.tenantId!, req.params.id, esValido, notas);
      if (!segmento) {
        return res.status(404).json({ error: 'Segmento no encontrado' });
      }
      res.json(segmento);
    } catch (error) {
      res.status(400).json({ error: (error as Error).message });
    }
  });

  /**
   * Delete segment
   * DELETE /api/gps/segmentos/:id
   */
  router.delete('/:id', async (req: TenantRequest, res: Response) => {
    try {
      const success = await service.delete(req.tenantId!, req.params.id);
      if (!success) {
        return res.status(404).json({ error: 'Segmento no encontrado' });
      }
      res.status(204).send();
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  return router;
}
