/**
 * PurchaseOrderConstruction Controller
 * API endpoints para extensión de órdenes de compra de construcción
 *
 * @module Purchase (MAI-004)
 * @prefix /api/v1/purchase-orders-construction
 */

import { Router, Request, Response, NextFunction } from 'express';
import {
  PurchaseOrderConstructionService,
  CreatePurchaseOrderConstructionDto,
  UpdatePurchaseOrderConstructionDto,
  RegisterReceptionDto,
} from '../services/purchase-order-construction.service';

const router = Router();
const purchaseOrderConstructionService = new PurchaseOrderConstructionService(null as any);

/**
 * GET /api/v1/purchase-orders-construction
 * Lista todas las extensiones de OC 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 { fraccionamientoId, requisicionId, qualityApproved, receivedFrom, receivedTo, page, limit } = req.query;

    const result = await purchaseOrderConstructionService.findAll(
      { tenantId },
      {
        fraccionamientoId: fraccionamientoId as string,
        requisicionId: requisicionId as string,
        qualityApproved: qualityApproved !== undefined ? qualityApproved === 'true' : undefined,
        receivedFrom: receivedFrom ? new Date(receivedFrom as string) : undefined,
        receivedTo: receivedTo ? new Date(receivedTo as string) : undefined,
        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/purchase-orders-construction/statistics
 * Estadísticas de recepción de OC
 */
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 { fraccionamientoId, dateFrom, dateTo } = req.query;

    const stats = await purchaseOrderConstructionService.getReceptionStatistics(
      { tenantId },
      fraccionamientoId as string,
      dateFrom ? new Date(dateFrom as string) : undefined,
      dateTo ? new Date(dateTo as string) : undefined,
    );

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

/**
 * GET /api/v1/purchase-orders-construction/pending-reception
 * OC pendientes de recepción
 */
router.get('/pending-reception', 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 { fraccionamientoId } = req.query;
    const data = await purchaseOrderConstructionService.findPendingReception(
      { tenantId },
      fraccionamientoId as string,
    );

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

/**
 * GET /api/v1/purchase-orders-construction/pending-quality
 * OC pendientes de aprobación de calidad
 */
router.get('/pending-quality', 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 purchaseOrderConstructionService.findPendingQualityApproval({ tenantId });

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

/**
 * GET /api/v1/purchase-orders-construction/by-po/:purchaseOrderId
 * Obtiene extensión por ID de orden de compra original
 */
router.get('/by-po/:purchaseOrderId', 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 purchaseOrderConstructionService.findByPurchaseOrderId(
      { tenantId },
      req.params.purchaseOrderId,
    );

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

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

/**
 * GET /api/v1/purchase-orders-construction/:id
 * Obtiene una extensión de OC 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 purchaseOrderConstructionService.findById({ tenantId }, req.params.id);
    if (!extension) {
      return res.status(404).json({ error: 'Extensión de OC no encontrada' });
    }

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

/**
 * POST /api/v1/purchase-orders-construction
 * Crea una nueva extensión de OC
 */
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: CreatePurchaseOrderConstructionDto = req.body;

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

    const extension = await purchaseOrderConstructionService.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/purchase-orders-construction/:id
 * Actualiza una extensión de OC
 */
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: UpdatePurchaseOrderConstructionDto = req.body;

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

    return res.json({ success: true, data: extension });
  } catch (error: any) {
    if (error.message?.includes('Cannot update')) {
      return res.status(400).json({ error: error.message });
    }
    return next(error);
  }
});

/**
 * POST /api/v1/purchase-orders-construction/:id/reception
 * Registra la recepción de una OC
 */
router.post('/:id/reception', 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: RegisterReceptionDto = {
      ...req.body,
      receivedById: req.body.receivedById || userId,
    };

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

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

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

/**
 * PATCH /api/v1/purchase-orders-construction/:id/quality
 * Actualiza el estado de calidad de una OC
 */
router.patch('/:id/quality', 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 { approved, notes } = req.body;

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

    const extension = await purchaseOrderConstructionService.updateQualityStatus(
      { tenantId, userId },
      req.params.id,
      approved,
      notes,
    );

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

    return res.json({ success: true, data: extension, message: 'Estado de calidad actualizado' });
  } catch (error: any) {
    if (error.message?.includes('before reception')) {
      return res.status(400).json({ error: error.message });
    }
    return next(error);
  }
});

/**
 * DELETE /api/v1/purchase-orders-construction/:id
 * Elimina una extensión de OC (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 purchaseOrderConstructionService.softDelete({ tenantId, userId }, req.params.id);

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

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

export default router;
