/**
 * Product Supplier Controller
 * API endpoints para gestion de proveedores de productos
 *
 * @module Products
 * @prefix /api/v1/products/:productId/suppliers
 */

import { Router, Request, Response, NextFunction } from 'express';
import {
  ProductSupplierService,
  CreateProductSupplierDto,
  UpdateProductSupplierDto
} from '../services/product-supplier.service';
import { ProductService } from '../services/product.service';

const router = Router({ mergeParams: true });
const supplierService = new ProductSupplierService();
const productService = new ProductService();

/**
 * GET /api/v1/products/:productId/suppliers
 * Lista todos los proveedores de un producto
 */
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 { productId } = req.params;
    const { isPreferred, isActive } = req.query;

    const product = await productService.findById(productId, tenantId);
    if (!product) {
      return res.status(404).json({ error: 'Producto no encontrado' });
    }

    const suppliers = await supplierService.findAll({
      productId,
      isPreferred: isPreferred === 'true' ? true : isPreferred === 'false' ? false : undefined,
      isActive: isActive === 'true' ? true : isActive === 'false' ? false : undefined,
    });

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

/**
 * GET /api/v1/products/:productId/suppliers/preferred
 * Obtiene el proveedor preferido de un producto
 */
router.get('/preferred', 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 { productId } = req.params;

    const product = await productService.findById(productId, tenantId);
    if (!product) {
      return res.status(404).json({ error: 'Producto no encontrado' });
    }

    const supplier = await supplierService.findPreferred(productId);

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

/**
 * GET /api/v1/products/:productId/suppliers/cheapest
 * Obtiene el proveedor mas barato de un producto
 */
router.get('/cheapest', 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 { productId } = req.params;

    const product = await productService.findById(productId, tenantId);
    if (!product) {
      return res.status(404).json({ error: 'Producto no encontrado' });
    }

    const supplier = await supplierService.findCheapest(productId);

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

/**
 * GET /api/v1/products/:productId/suppliers/stats
 * Obtiene estadisticas de precios de proveedores
 */
router.get('/stats', 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 { productId } = req.params;

    const product = await productService.findById(productId, tenantId);
    if (!product) {
      return res.status(404).json({ error: 'Producto no encontrado' });
    }

    const [count, avgPrice, minPrice] = await Promise.all([
      supplierService.countByProduct(productId),
      supplierService.getAveragePurchasePrice(productId),
      supplierService.getLowestPurchasePrice(productId),
    ]);

    return res.json({
      success: true,
      data: {
        suppliersCount: count,
        averagePurchasePrice: avgPrice,
        lowestPurchasePrice: minPrice,
      },
    });
  } catch (error) {
    return next(error);
  }
});

/**
 * GET /api/v1/products/:productId/suppliers/:id
 * Obtiene un 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 supplier = await supplierService.findById(req.params.id);
    if (!supplier || supplier.productId !== req.params.productId) {
      return res.status(404).json({ error: 'Proveedor no encontrado' });
    }

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

/**
 * POST /api/v1/products/:productId/suppliers
 * Asocia un proveedor a un producto
 */
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 { productId } = req.params;

    const product = await productService.findById(productId, tenantId);
    if (!product) {
      return res.status(404).json({ error: 'Producto no encontrado' });
    }

    const data: CreateProductSupplierDto = {
      ...req.body,
      productId,
    };

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

    const existing = await supplierService.findByProductAndSupplier(productId, data.supplierId);
    if (existing) {
      return res.status(409).json({
        error: 'Este proveedor ya esta asociado a este producto'
      });
    }

    const supplier = await supplierService.create(data);
    return res.status(201).json({ success: true, data: supplier });
  } catch (error) {
    return next(error);
  }
});

/**
 * PATCH /api/v1/products/:productId/suppliers/:id
 * Actualiza la relacion proveedor-producto
 */
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 data: UpdateProductSupplierDto = req.body;
    const supplier = await supplierService.update(req.params.id, data);

    if (!supplier || supplier.productId !== req.params.productId) {
      return res.status(404).json({ error: 'Proveedor no encontrado' });
    }

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

/**
 * PATCH /api/v1/products/:productId/suppliers/:id/set-preferred
 * Establece un proveedor como preferido
 */
router.patch('/:id/set-preferred', 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 existing = await supplierService.findById(req.params.id);
    if (!existing || existing.productId !== req.params.productId) {
      return res.status(404).json({ error: 'Proveedor no encontrado' });
    }

    const supplier = await supplierService.setPreferred(req.params.id);
    if (!supplier) {
      return res.status(404).json({ error: 'Proveedor no encontrado' });
    }

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

/**
 * PATCH /api/v1/products/:productId/suppliers/:id/update-price
 * Actualiza el precio de compra
 */
router.patch('/:id/update-price', 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 { purchasePrice, currency } = req.body;
    if (purchasePrice === undefined) {
      return res.status(400).json({ error: 'purchasePrice es requerido' });
    }

    const existing = await supplierService.findById(req.params.id);
    if (!existing || existing.productId !== req.params.productId) {
      return res.status(404).json({ error: 'Proveedor no encontrado' });
    }

    const supplier = await supplierService.updatePurchasePrice(
      req.params.id,
      purchasePrice,
      currency
    );

    if (!supplier) {
      return res.status(404).json({ error: 'Proveedor no encontrado' });
    }

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

/**
 * DELETE /api/v1/products/:productId/suppliers/:id
 * Elimina la relacion proveedor-producto
 */
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 existing = await supplierService.findById(req.params.id);
    if (!existing || existing.productId !== req.params.productId) {
      return res.status(404).json({ error: 'Proveedor no encontrado' });
    }

    const deleted = await supplierService.delete(req.params.id);
    if (!deleted) {
      return res.status(404).json({ error: 'Proveedor no encontrado' });
    }

    return res.json({ success: true, message: 'Proveedor desvinculado del producto' });
  } catch (error) {
    return next(error);
  }
});

export default router;
