/**
 * Service Order Controller
 * Mecánicas Diesel - ERP Suite
 *
 * REST API endpoints for service orders.
 */

import { Router, Request, Response, NextFunction } from 'express';
import { DataSource } from 'typeorm';
import { ServiceOrderService, ServiceOrderFilters } from '../services/service-order.service';
import { ServiceOrderStatus, ServiceOrderPriority } from '../entities/service-order.entity';
import { OrderItemType } from '../entities/order-item.entity';

// Middleware type for tenant extraction
interface TenantRequest extends Request {
  tenantId?: string;
  userId?: string;
}

export function createServiceOrderController(dataSource: DataSource): Router {
  const router = Router();
  const service = new ServiceOrderService(dataSource);

  // Middleware to extract tenant from request
  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 service order
   * POST /api/service-orders
   */
  router.post('/', async (req: TenantRequest, res: Response) => {
    try {
      const order = await service.create(req.tenantId!, req.body, req.userId);
      res.status(201).json(order);
    } catch (error) {
      res.status(400).json({ error: (error as Error).message });
    }
  });

  /**
   * List service orders with filters
   * GET /api/service-orders
   */
  router.get('/', async (req: TenantRequest, res: Response) => {
    try {
      const filters: ServiceOrderFilters = {
        status: req.query.status as ServiceOrderStatus,
        priority: req.query.priority as ServiceOrderPriority,
        customerId: req.query.customerId as string,
        vehicleId: req.query.vehicleId as string,
        assignedTo: req.query.assignedTo as string,
        bayId: req.query.bayId as string,
        search: req.query.search as string,
        fromDate: req.query.fromDate ? new Date(req.query.fromDate as string) : undefined,
        toDate: req.query.toDate ? new Date(req.query.toDate 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 orders grouped by status (Kanban)
   * GET /api/service-orders/kanban
   */
  router.get('/kanban', async (req: TenantRequest, res: Response) => {
    try {
      const result = await service.getOrdersByStatus(req.tenantId!);
      res.json(result);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * Get dashboard statistics
   * GET /api/service-orders/stats
   */
  router.get('/stats', async (req: TenantRequest, res: Response) => {
    try {
      const stats = await service.getDashboardStats(req.tenantId!);
      res.json(stats);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

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

  /**
   * Get by order number
   * GET /api/service-orders/number/:orderNumber
   */
  router.get('/number/:orderNumber', async (req: TenantRequest, res: Response) => {
    try {
      const order = await service.findByOrderNumber(req.tenantId!, req.params.orderNumber);
      if (!order) {
        return res.status(404).json({ error: 'Service order not found' });
      }
      res.json(order);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

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

  /**
   * Add item to order
   * POST /api/service-orders/:id/items
   */
  router.post('/:id/items', async (req: TenantRequest, res: Response) => {
    try {
      const item = await service.addItem(req.tenantId!, req.params.id, req.body);
      if (!item) {
        return res.status(404).json({ error: 'Service order not found' });
      }
      res.status(201).json(item);
    } catch (error) {
      res.status(400).json({ error: (error as Error).message });
    }
  });

  /**
   * Get order items
   * GET /api/service-orders/:id/items
   */
  router.get('/:id/items', async (req: TenantRequest, res: Response) => {
    try {
      const items = await service.getItems(req.params.id);
      res.json(items);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * Update order item
   * PATCH /api/service-orders/:id/items/:itemId
   */
  router.patch('/:id/items/:itemId', async (req: TenantRequest, res: Response) => {
    try {
      const item = await service.updateItem(req.params.itemId, req.body);
      if (!item) {
        return res.status(404).json({ error: 'Item not found' });
      }
      res.json(item);
    } catch (error) {
      res.status(400).json({ error: (error as Error).message });
    }
  });

  /**
   * Remove order item
   * DELETE /api/service-orders/:id/items/:itemId
   */
  router.delete('/:id/items/:itemId', async (req: TenantRequest, res: Response) => {
    try {
      const success = await service.removeItem(req.params.itemId);
      if (!success) {
        return res.status(404).json({ error: 'Item not found' });
      }
      res.status(204).send();
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  return router;
}
