/**
 * Vehicle Controller
 * Mecánicas Diesel - ERP Suite
 *
 * REST API endpoints for vehicle management.
 */

import { Router, Request, Response, NextFunction } from 'express';
import { DataSource } from 'typeorm';
import { VehicleService, VehicleFilters } from '../services/vehicle.service';
import { VehicleType, VehicleStatus } from '../entities/vehicle.entity';

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

export function createVehicleController(dataSource: DataSource): Router {
  const router = Router();
  const service = new VehicleService(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 is required' });
    }
    req.tenantId = tenantId;
    req.userId = req.headers['x-user-id'] as string;
    next();
  };

  router.use(extractTenant);

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

  /**
   * List vehicles with filters
   * GET /api/vehicles
   */
  router.get('/', async (req: TenantRequest, res: Response) => {
    try {
      const filters: VehicleFilters = {
        customerId: req.query.customerId as string,
        fleetId: req.query.fleetId as string,
        make: req.query.make as string,
        model: req.query.model as string,
        year: req.query.year ? parseInt(req.query.year as string, 10) : undefined,
        vehicleType: req.query.vehicleType as VehicleType,
        search: req.query.search as string,
        status: req.query.status as VehicleStatus,
      };

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

  /**
   * Get unique makes
   * GET /api/vehicles/makes
   */
  router.get('/makes', async (req: TenantRequest, res: Response) => {
    try {
      const makes = await service.getMakes(req.tenantId!);
      res.json(makes);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * Get models for a make
   * GET /api/vehicles/makes/:make/models
   */
  router.get('/makes/:make/models', async (req: TenantRequest, res: Response) => {
    try {
      const models = await service.getModels(req.tenantId!, req.params.make);
      res.json(models);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * Get a single vehicle
   * GET /api/vehicles/:id
   */
  router.get('/:id', async (req: TenantRequest, res: Response) => {
    try {
      const vehicle = await service.findById(req.tenantId!, req.params.id);
      if (!vehicle) {
        return res.status(404).json({ error: 'Vehicle not found' });
      }
      res.json(vehicle);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * Get by plate number
   * GET /api/vehicles/plate/:licensePlate
   */
  router.get('/plate/:licensePlate', async (req: TenantRequest, res: Response) => {
    try {
      const vehicle = await service.findByPlate(req.tenantId!, req.params.licensePlate);
      if (!vehicle) {
        return res.status(404).json({ error: 'Vehicle not found' });
      }
      res.json(vehicle);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * Get by VIN
   * GET /api/vehicles/vin/:vin
   */
  router.get('/vin/:vin', async (req: TenantRequest, res: Response) => {
    try {
      const vehicle = await service.findByVin(req.tenantId!, req.params.vin);
      if (!vehicle) {
        return res.status(404).json({ error: 'Vehicle not found' });
      }
      res.json(vehicle);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * Get customer's vehicles
   * GET /api/vehicles/customer/:customerId
   */
  router.get('/customer/:customerId', async (req: TenantRequest, res: Response) => {
    try {
      const vehicles = await service.findByCustomer(req.tenantId!, req.params.customerId);
      res.json(vehicles);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * Get fleet's vehicles
   * GET /api/vehicles/fleet/:fleetId
   */
  router.get('/fleet/:fleetId', async (req: TenantRequest, res: Response) => {
    try {
      const vehicles = await service.findByFleet(req.tenantId!, req.params.fleetId);
      res.json(vehicles);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * Update vehicle
   * PATCH /api/vehicles/:id
   */
  router.patch('/:id', async (req: TenantRequest, res: Response) => {
    try {
      const vehicle = await service.update(req.tenantId!, req.params.id, req.body);
      if (!vehicle) {
        return res.status(404).json({ error: 'Vehicle not found' });
      }
      res.json(vehicle);
    } catch (error) {
      res.status(400).json({ error: (error as Error).message });
    }
  });

  /**
   * Update odometer
   * PATCH /api/vehicles/:id/odometer
   */
  router.patch('/:id/odometer', async (req: TenantRequest, res: Response) => {
    try {
      const vehicle = await service.updateOdometer(req.tenantId!, req.params.id, req.body.odometer);
      if (!vehicle) {
        return res.status(404).json({ error: 'Vehicle not found' });
      }
      res.json(vehicle);
    } catch (error) {
      res.status(400).json({ error: (error as Error).message });
    }
  });

  /**
   * Deactivate vehicle
   * DELETE /api/vehicles/: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: 'Vehicle not found' });
      }
      res.status(204).send();
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  return router;
}
