/**
 * Product Price Controller
 * API endpoints para gestion de precios de productos
 *
 * @module Products
 * @prefix /api/v1/products/:productId/prices
 */

import { Router, Request, Response, NextFunction } from 'express';
import {
  ProductPriceService,
  CreateProductPriceDto,
  UpdateProductPriceDto
} from '../services/product-price.service';
import { ProductService } from '../services/product.service';

const router = Router({ mergeParams: true });
const priceService = new ProductPriceService();
const productService = new ProductService();

/**
 * GET /api/v1/products/:productId/prices
 * Lista todos los precios 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 { priceType, isActive, activeOnly } = req.query;

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

    let prices;
    if (activeOnly === 'true') {
      prices = await priceService.findActivePricesByProduct(productId);
    } else {
      prices = await priceService.findAll({
        productId,
        priceType: priceType as 'standard' | 'wholesale' | 'retail' | 'promo',
        isActive: isActive === 'true' ? true : isActive === 'false' ? false : undefined,
      });
    }

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

/**
 * GET /api/v1/products/:productId/prices/best
 * Obtiene el mejor precio para una cantidad dada
 */
router.get('/best', 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 { quantity } = req.query;

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

    const price = await priceService.findBestPrice(
      productId,
      quantity ? parseInt(quantity as string, 10) : 1
    );

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

/**
 * GET /api/v1/products/:productId/prices/active
 * Obtiene el precio activo por tipo
 */
router.get('/active', 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 { priceType, quantity } = req.query;

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

    const price = await priceService.findActivePrice(
      productId,
      (priceType as 'standard' | 'wholesale' | 'retail' | 'promo') || 'standard',
      quantity ? parseInt(quantity as string, 10) : 1
    );

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

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

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

/**
 * POST /api/v1/products/:productId/prices
 * Crea un nuevo precio para 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: CreateProductPriceDto = {
      ...req.body,
      productId,
    };

    if (data.price === undefined || data.price === null) {
      return res.status(400).json({
        error: 'price es requerido'
      });
    }

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

/**
 * POST /api/v1/products/:productId/prices/standard
 * Establece el precio estandar de un producto
 */
router.post('/standard', 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 { price, currency } = req.body;

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

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

    const productPrice = await priceService.setStandardPrice(productId, price, currency);
    return res.json({ success: true, data: productPrice });
  } catch (error) {
    return next(error);
  }
});

/**
 * POST /api/v1/products/:productId/prices/promo
 * Crea un precio promocional para un producto
 */
router.post('/promo', 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 { price, validFrom, validTo, priceListName } = req.body;

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

    if (price === undefined || !validFrom || !validTo) {
      return res.status(400).json({
        error: 'price, validFrom y validTo son requeridos'
      });
    }

    const productPrice = await priceService.createPromoPrice(
      productId,
      price,
      new Date(validFrom),
      new Date(validTo),
      priceListName
    );

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

/**
 * PATCH /api/v1/products/:productId/prices/:id
 * Actualiza un precio
 */
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: UpdateProductPriceDto = req.body;
    const price = await priceService.update(req.params.id, data);

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

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

/**
 * PATCH /api/v1/products/:productId/prices/:id/deactivate
 * Desactiva un precio
 */
router.patch('/:id/deactivate', 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 price = await priceService.deactivate(req.params.id);

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

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

/**
 * DELETE /api/v1/products/:productId/prices/:id
 * Elimina un precio
 */
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 price = await priceService.findById(req.params.id);
    if (!price || price.productId !== req.params.productId) {
      return res.status(404).json({ error: 'Precio no encontrado' });
    }

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

    return res.json({ success: true, message: 'Precio eliminado' });
  } catch (error) {
    return next(error);
  }
});

export default router;
