/**
 * DispositivoGps Controller
 * ERP Transportistas
 *
 * REST API endpoints for GPS device 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 { DispositivoGpsService, DispositivoGpsFilters } from '../services/dispositivo-gps.service';
import { PlataformaGps, TipoUnidadGps } from '../entities/dispositivo-gps.entity';

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

export function createDispositivoGpsController(dataSource: DataSource): Router {
  const router = Router();
  const service = new DispositivoGpsService(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);

  /**
   * Register a new GPS device
   * POST /api/gps/dispositivos
   */
  router.post('/', async (req: TenantRequest, res: Response) => {
    try {
      const dispositivo = await service.create(req.tenantId!, {
        ...req.body,
        createdBy: req.userId,
      });
      res.status(201).json(dispositivo);
    } catch (error) {
      res.status(400).json({ error: (error as Error).message });
    }
  });

  /**
   * List GPS devices with filters
   * GET /api/gps/dispositivos
   */
  router.get('/', async (req: TenantRequest, res: Response) => {
    try {
      const filters: DispositivoGpsFilters = {
        unidadId: req.query.unidadId as string,
        tipoUnidad: req.query.tipoUnidad as TipoUnidadGps,
        plataforma: req.query.plataforma as PlataformaGps,
        activo: req.query.activo === 'true' ? true : req.query.activo === 'false' ? false : undefined,
        search: req.query.search as string,
      };

      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 device statistics
   * GET /api/gps/dispositivos/estadisticas
   */
  router.get('/estadisticas', async (req: TenantRequest, res: Response) => {
    try {
      const stats = await service.getEstadisticas(req.tenantId!);
      res.json(stats);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * Get all active devices with positions (for map view)
   * GET /api/gps/dispositivos/activos
   */
  router.get('/activos', async (req: TenantRequest, res: Response) => {
    try {
      const dispositivos = await service.findActivosConPosicion(req.tenantId!);
      res.json(dispositivos);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * Get devices with stale positions
   * GET /api/gps/dispositivos/inactivos
   */
  router.get('/inactivos', async (req: TenantRequest, res: Response) => {
    try {
      const umbralMinutos = parseInt(req.query.umbral as string, 10) || 10;
      const dispositivos = await service.findDispositivosInactivos(req.tenantId!, umbralMinutos);
      res.json(dispositivos);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

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

  /**
   * Get device by unit ID
   * GET /api/gps/dispositivos/unidad/:unidadId
   */
  router.get('/unidad/:unidadId', async (req: TenantRequest, res: Response) => {
    try {
      const dispositivo = await service.findByUnidadId(req.tenantId!, req.params.unidadId);
      if (!dispositivo) {
        return res.status(404).json({ error: 'Dispositivo GPS no encontrado para la unidad' });
      }
      res.json(dispositivo);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * Get device by external ID
   * GET /api/gps/dispositivos/external/:externalId
   */
  router.get('/external/:externalId', async (req: TenantRequest, res: Response) => {
    try {
      const dispositivo = await service.findByExternalId(req.tenantId!, req.params.externalId);
      if (!dispositivo) {
        return res.status(404).json({ error: 'Dispositivo GPS no encontrado' });
      }
      res.json(dispositivo);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * Update GPS device
   * PATCH /api/gps/dispositivos/:id
   */
  router.patch('/:id', async (req: TenantRequest, res: Response) => {
    try {
      const dispositivo = await service.update(req.tenantId!, req.params.id, req.body);
      if (!dispositivo) {
        return res.status(404).json({ error: 'Dispositivo GPS no encontrado' });
      }
      res.json(dispositivo);
    } catch (error) {
      res.status(400).json({ error: (error as Error).message });
    }
  });

  /**
   * Update last position
   * PATCH /api/gps/dispositivos/:id/posicion
   */
  router.patch('/:id/posicion', async (req: TenantRequest, res: Response) => {
    try {
      const { latitud, longitud, timestamp } = req.body;
      const dispositivo = await service.updateUltimaPosicion(req.tenantId!, req.params.id, {
        latitud,
        longitud,
        timestamp: new Date(timestamp),
      });
      if (!dispositivo) {
        return res.status(404).json({ error: 'Dispositivo GPS no encontrado' });
      }
      res.json(dispositivo);
    } catch (error) {
      res.status(400).json({ error: (error as Error).message });
    }
  });

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

  return router;
}
