/**
 * Part Controller
 * Mecánicas Diesel - ERP Suite
 *
 * REST API endpoints for parts/inventory management.
 */

import { Router, Request, Response, NextFunction } from 'express';
import { DataSource } from 'typeorm';
import { PartService, PartFilters } from '../services/part.service';

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

export function createPartController(dataSource: DataSource): Router {
  const router = Router();
  const service = new PartService(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 part
   * POST /api/parts
   */
  router.post('/', async (req: TenantRequest, res: Response) => {
    try {
      const part = await service.create(req.tenantId!, req.body);
      res.status(201).json(part);
    } catch (error) {
      res.status(400).json({ error: (error as Error).message });
    }
  });

  /**
   * List parts with filters
   * GET /api/parts
   */
  router.get('/', async (req: TenantRequest, res: Response) => {
    try {
      const filters: PartFilters = {
        categoryId: req.query.categoryId as string,
        preferredSupplierId: req.query.supplierId as string,
        brand: req.query.brand as string,
        search: req.query.search as string,
        lowStock: req.query.lowStock === 'true',
        isActive: req.query.isActive === 'true' ? true : req.query.isActive === 'false' ? false : 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 inventory statistics
   * GET /api/parts/stats
   */
  router.get('/stats', async (req: TenantRequest, res: Response) => {
    try {
      const stats = await service.getInventoryValue(req.tenantId!);
      res.json(stats);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * Get parts with low stock
   * GET /api/parts/low-stock
   */
  router.get('/low-stock', async (req: TenantRequest, res: Response) => {
    try {
      const parts = await service.getLowStockParts(req.tenantId!);
      res.json(parts);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * Search parts (for autocomplete)
   * GET /api/parts/search
   */
  router.get('/search', async (req: TenantRequest, res: Response) => {
    try {
      const query = req.query.q as string || '';
      const limit = Math.min(parseInt(req.query.limit as string, 10) || 10, 50);
      const parts = await service.search(req.tenantId!, query, limit);
      res.json(parts);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

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

  /**
   * Get by SKU
   * GET /api/parts/sku/:sku
   */
  router.get('/sku/:sku', async (req: TenantRequest, res: Response) => {
    try {
      const part = await service.findBySku(req.tenantId!, req.params.sku);
      if (!part) {
        return res.status(404).json({ error: 'Part not found' });
      }
      res.json(part);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

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

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

  /**
   * Adjust stock
   * POST /api/parts/:id/stock-adjustment
   */
  router.post('/:id/stock-adjustment', async (req: TenantRequest, res: Response) => {
    try {
      const part = await service.adjustStock(req.tenantId!, req.params.id, req.body);
      if (!part) {
        return res.status(404).json({ error: 'Part not found' });
      }
      res.json(part);
    } catch (error) {
      res.status(400).json({ error: (error as Error).message });
    }
  });

  /**
   * Reserve stock
   * POST /api/parts/:id/reserve
   */
  router.post('/:id/reserve', async (req: TenantRequest, res: Response) => {
    try {
      const success = await service.reserveStock(req.tenantId!, req.params.id, req.body.quantity);
      if (!success) {
        return res.status(404).json({ error: 'Part not found' });
      }
      res.status(204).send();
    } catch (error) {
      res.status(400).json({ error: (error as Error).message });
    }
  });

  /**
   * Release reserved stock
   * POST /api/parts/:id/release
   */
  router.post('/:id/release', async (req: TenantRequest, res: Response) => {
    try {
      const success = await service.releaseStock(req.tenantId!, req.params.id, req.body.quantity);
      if (!success) {
        return res.status(404).json({ error: 'Part not found' });
      }
      res.status(204).send();
    } catch (error) {
      res.status(400).json({ error: (error as Error).message });
    }
  });

  /**
   * Consume stock (order completed)
   * POST /api/parts/:id/consume
   */
  router.post('/:id/consume', async (req: TenantRequest, res: Response) => {
    try {
      const success = await service.consumeStock(req.tenantId!, req.params.id, req.body.quantity);
      if (!success) {
        return res.status(404).json({ error: 'Part not found' });
      }
      res.status(204).send();
    } catch (error) {
      res.status(400).json({ error: (error as Error).message });
    }
  });

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

  return router;
}
