/**
 * SupplierConstruction Controller
 * API endpoints para extensión de proveedores de construcción
 *
 * @module Purchase (MAI-004)
 * @prefix /api/v1/suppliers-construction
 */

import { Router, Request, Response, NextFunction } from 'express';
import {
  SupplierConstructionService,
  CreateSupplierConstructionDto,
  UpdateSupplierConstructionDto,
  EvaluateSupplierDto,
} from '../services/supplier-construction.service';

const router = Router();
const supplierConstructionService = new SupplierConstructionService(null as any);

/**
 * GET /api/v1/suppliers-construction
 * Lista todas las extensiones de proveedores del tenant
 */
router.get('/', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const tenantId = req.headers['x-tenant-id'] as string;
    if (!tenantId) {
      return res.status(400).json({ error: 'X-Tenant-Id header required' });
    }

    const { isMaterialsSupplier, isServicesSupplier, isEquipmentSupplier, minRating, hasValidDocuments, specialty, page, limit } = req.query;

    const result = await supplierConstructionService.findAll(
      { tenantId },
      {
        isMaterialsSupplier: isMaterialsSupplier !== undefined ? isMaterialsSupplier === 'true' : undefined,
        isServicesSupplier: isServicesSupplier !== undefined ? isServicesSupplier === 'true' : undefined,
        isEquipmentSupplier: isEquipmentSupplier !== undefined ? isEquipmentSupplier === 'true' : undefined,
        minRating: minRating ? Number(minRating) : undefined,
        hasValidDocuments: hasValidDocuments !== undefined ? hasValidDocuments === 'true' : undefined,
        specialty: specialty as string,
        page: page ? Number(page) : undefined,
        limit: limit ? Number(limit) : undefined,
      },
    );

    return res.json({
      success: true,
      data: result.data,
      total: result.total,
      page: result.page,
      limit: result.limit,
    });
  } catch (error) {
    return next(error);
  }
});

/**
 * GET /api/v1/suppliers-construction/statistics
 * Estadísticas de proveedores
 */
router.get('/statistics', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const tenantId = req.headers['x-tenant-id'] as string;
    if (!tenantId) {
      return res.status(400).json({ error: 'X-Tenant-Id header required' });
    }

    const stats = await supplierConstructionService.getSupplierStatistics({ tenantId });
    return res.json({ success: true, data: stats });
  } catch (error) {
    return next(error);
  }
});

/**
 * GET /api/v1/suppliers-construction/top-rated
 * Proveedores mejor calificados
 */
router.get('/top-rated', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const tenantId = req.headers['x-tenant-id'] as string;
    if (!tenantId) {
      return res.status(400).json({ error: 'X-Tenant-Id header required' });
    }

    const { limit } = req.query;
    const data = await supplierConstructionService.findTopRated({ tenantId }, limit ? Number(limit) : 10);

    return res.json({ success: true, data, count: data.length });
  } catch (error) {
    return next(error);
  }
});

/**
 * GET /api/v1/suppliers-construction/by-specialty/:specialty
 * Proveedores por especialidad
 */
router.get('/by-specialty/:specialty', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const tenantId = req.headers['x-tenant-id'] as string;
    if (!tenantId) {
      return res.status(400).json({ error: 'X-Tenant-Id header required' });
    }

    const data = await supplierConstructionService.findBySpecialty({ tenantId }, req.params.specialty);
    return res.json({ success: true, data, count: data.length });
  } catch (error) {
    return next(error);
  }
});

/**
 * GET /api/v1/suppliers-construction/materials
 * Proveedores de materiales
 */
router.get('/materials', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const tenantId = req.headers['x-tenant-id'] as string;
    if (!tenantId) {
      return res.status(400).json({ error: 'X-Tenant-Id header required' });
    }

    const data = await supplierConstructionService.findMaterialsSuppliers({ tenantId });
    return res.json({ success: true, data, count: data.length });
  } catch (error) {
    return next(error);
  }
});

/**
 * GET /api/v1/suppliers-construction/services
 * Proveedores de servicios
 */
router.get('/services', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const tenantId = req.headers['x-tenant-id'] as string;
    if (!tenantId) {
      return res.status(400).json({ error: 'X-Tenant-Id header required' });
    }

    const data = await supplierConstructionService.findServicesSuppliers({ tenantId });
    return res.json({ success: true, data, count: data.length });
  } catch (error) {
    return next(error);
  }
});

/**
 * GET /api/v1/suppliers-construction/equipment
 * Proveedores de equipos
 */
router.get('/equipment', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const tenantId = req.headers['x-tenant-id'] as string;
    if (!tenantId) {
      return res.status(400).json({ error: 'X-Tenant-Id header required' });
    }

    const data = await supplierConstructionService.findEquipmentSuppliers({ tenantId });
    return res.json({ success: true, data, count: data.length });
  } catch (error) {
    return next(error);
  }
});

/**
 * GET /api/v1/suppliers-construction/expiring-documents
 * Proveedores con documentos por vencer
 */
router.get('/expiring-documents', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const tenantId = req.headers['x-tenant-id'] as string;
    if (!tenantId) {
      return res.status(400).json({ error: 'X-Tenant-Id header required' });
    }

    const { daysAhead } = req.query;
    const data = await supplierConstructionService.findWithExpiringDocuments(
      { tenantId },
      daysAhead ? Number(daysAhead) : 30,
    );

    return res.json({ success: true, data, count: data.length });
  } catch (error) {
    return next(error);
  }
});

/**
 * GET /api/v1/suppliers-construction/by-supplier/:supplierId
 * Obtiene extensión por ID de proveedor original
 */
router.get('/by-supplier/:supplierId', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const tenantId = req.headers['x-tenant-id'] as string;
    if (!tenantId) {
      return res.status(400).json({ error: 'X-Tenant-Id header required' });
    }

    const extension = await supplierConstructionService.findBySupplierId({ tenantId }, req.params.supplierId);
    if (!extension) {
      return res.status(404).json({ error: 'Extensión de proveedor no encontrada' });
    }

    return res.json({ success: true, data: extension });
  } catch (error) {
    return next(error);
  }
});

/**
 * GET /api/v1/suppliers-construction/:id
 * Obtiene una extensión de proveedor por ID
 */
router.get('/:id', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const tenantId = req.headers['x-tenant-id'] as string;
    if (!tenantId) {
      return res.status(400).json({ error: 'X-Tenant-Id header required' });
    }

    const extension = await supplierConstructionService.findById({ tenantId }, req.params.id);
    if (!extension) {
      return res.status(404).json({ error: 'Extensión de proveedor no encontrada' });
    }

    return res.json({ success: true, data: extension });
  } catch (error) {
    return next(error);
  }
});

/**
 * POST /api/v1/suppliers-construction
 * Crea una nueva extensión de proveedor
 */
router.post('/', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const tenantId = req.headers['x-tenant-id'] as string;
    if (!tenantId) {
      return res.status(400).json({ error: 'X-Tenant-Id header required' });
    }

    const userId = (req as any).user?.id;
    const dto: CreateSupplierConstructionDto = req.body;

    if (!dto.supplierId) {
      return res.status(400).json({ error: 'supplierId es requerido' });
    }

    const extension = await supplierConstructionService.create({ tenantId, userId }, dto);
    return res.status(201).json({ success: true, data: extension });
  } catch (error: any) {
    if (error.message?.includes('already exists')) {
      return res.status(409).json({ error: error.message });
    }
    return next(error);
  }
});

/**
 * PATCH /api/v1/suppliers-construction/:id
 * Actualiza una extensión de proveedor
 */
router.patch('/:id', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const tenantId = req.headers['x-tenant-id'] as string;
    if (!tenantId) {
      return res.status(400).json({ error: 'X-Tenant-Id header required' });
    }

    const userId = (req as any).user?.id;
    const dto: UpdateSupplierConstructionDto = req.body;

    const extension = await supplierConstructionService.update({ tenantId, userId }, req.params.id, dto);
    if (!extension) {
      return res.status(404).json({ error: 'Extensión de proveedor no encontrada' });
    }

    return res.json({ success: true, data: extension });
  } catch (error) {
    return next(error);
  }
});

/**
 * POST /api/v1/suppliers-construction/:id/evaluate
 * Evalúa un proveedor
 */
router.post('/:id/evaluate', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const tenantId = req.headers['x-tenant-id'] as string;
    if (!tenantId) {
      return res.status(400).json({ error: 'X-Tenant-Id header required' });
    }

    const userId = (req as any).user?.id;
    const dto: EvaluateSupplierDto = req.body;

    if (dto.qualityRating === undefined || dto.deliveryRating === undefined || dto.priceRating === undefined) {
      return res.status(400).json({ error: 'qualityRating, deliveryRating y priceRating son requeridos' });
    }

    const extension = await supplierConstructionService.evaluate({ tenantId, userId }, req.params.id, dto);
    if (!extension) {
      return res.status(404).json({ error: 'Extensión de proveedor no encontrada' });
    }

    return res.json({ success: true, data: extension, message: 'Evaluación registrada' });
  } catch (error: any) {
    if (error.message?.includes('between')) {
      return res.status(400).json({ error: error.message });
    }
    return next(error);
  }
});

/**
 * PATCH /api/v1/suppliers-construction/:id/documents
 * Actualiza el estado de documentos de un proveedor
 */
router.patch('/:id/documents', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const tenantId = req.headers['x-tenant-id'] as string;
    if (!tenantId) {
      return res.status(400).json({ error: 'X-Tenant-Id header required' });
    }

    const userId = (req as any).user?.id;
    const { hasValidDocuments, expiryDate } = req.body;

    if (hasValidDocuments === undefined) {
      return res.status(400).json({ error: 'hasValidDocuments es requerido' });
    }

    const extension = await supplierConstructionService.updateDocumentStatus(
      { tenantId, userId },
      req.params.id,
      hasValidDocuments,
      expiryDate ? new Date(expiryDate) : undefined,
    );

    if (!extension) {
      return res.status(404).json({ error: 'Extensión de proveedor no encontrada' });
    }

    return res.json({ success: true, data: extension, message: 'Estado de documentos actualizado' });
  } catch (error) {
    return next(error);
  }
});

/**
 * PATCH /api/v1/suppliers-construction/:id/credit
 * Actualiza los términos de crédito de un proveedor
 */
router.patch('/:id/credit', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const tenantId = req.headers['x-tenant-id'] as string;
    if (!tenantId) {
      return res.status(400).json({ error: 'X-Tenant-Id header required' });
    }

    const userId = (req as any).user?.id;
    const { creditLimit, paymentDays } = req.body;

    if (creditLimit === undefined || paymentDays === undefined) {
      return res.status(400).json({ error: 'creditLimit y paymentDays son requeridos' });
    }

    const extension = await supplierConstructionService.updateCreditTerms(
      { tenantId, userId },
      req.params.id,
      Number(creditLimit),
      Number(paymentDays),
    );

    if (!extension) {
      return res.status(404).json({ error: 'Extensión de proveedor no encontrada' });
    }

    return res.json({ success: true, data: extension, message: 'Términos de crédito actualizados' });
  } catch (error: any) {
    if (error.message?.includes('cannot be negative')) {
      return res.status(400).json({ error: error.message });
    }
    return next(error);
  }
});

/**
 * DELETE /api/v1/suppliers-construction/:id
 * Elimina una extensión de proveedor (soft delete)
 */
router.delete('/:id', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const tenantId = req.headers['x-tenant-id'] as string;
    if (!tenantId) {
      return res.status(400).json({ error: 'X-Tenant-Id header required' });
    }

    const userId = (req as any).user?.id;
    const deleted = await supplierConstructionService.softDelete({ tenantId, userId }, req.params.id);

    if (!deleted) {
      return res.status(404).json({ error: 'Extensión de proveedor no encontrada' });
    }

    return res.json({ success: true, message: 'Extensión de proveedor eliminada' });
  } catch (error) {
    return next(error);
  }
});

export default router;
