/**
 * Product Category Controller
 * API endpoints para gestion de categorias de productos
 *
 * @module Products
 * @prefix /api/v1/products/categories
 */

import { Router, Request, Response, NextFunction } from 'express';
import {
  ProductCategoryService,
  CreateProductCategoryDto,
  UpdateProductCategoryDto
} from '../services/product-category.service';

const router = Router();
const categoryService = new ProductCategoryService();

/**
 * GET /api/v1/products/categories
 * Lista todas las categorias 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 { parentId, isActive, search } = req.query;

    const categories = await categoryService.findAll({
      tenantId,
      parentId: parentId === 'null' ? null : (parentId as string),
      isActive: isActive === 'true' ? true : isActive === 'false' ? false : undefined,
      search: search as string,
    });

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

/**
 * GET /api/v1/products/categories/tree
 * Obtiene el arbol jerarquico de categorias
 */
router.get('/tree', 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 tree = await categoryService.getHierarchyTree(tenantId);

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

/**
 * GET /api/v1/products/categories/roots
 * Obtiene las categorias raiz (sin padre)
 */
router.get('/roots', 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 categories = await categoryService.findRootCategories(tenantId);

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

/**
 * GET /api/v1/products/categories/:id
 * Obtiene una categoria 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 category = await categoryService.findById(req.params.id, tenantId);
    if (!category) {
      return res.status(404).json({ error: 'Categoria no encontrada' });
    }

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

/**
 * GET /api/v1/products/categories/:id/children
 * Obtiene las subcategorias de una categoria
 */
router.get('/:id/children', 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 children = await categoryService.findChildren(req.params.id, tenantId);

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

/**
 * GET /api/v1/products/categories/:id/products/count
 * Cuenta los productos en una categoria
 */
router.get('/:id/products/count', 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 count = await categoryService.countProducts(req.params.id, tenantId);

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

/**
 * POST /api/v1/products/categories
 * Crea una nueva categoria
 */
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 data: CreateProductCategoryDto = {
      ...req.body,
      tenantId,
    };

    if (!data.code || !data.name) {
      return res.status(400).json({
        error: 'code y name son requeridos'
      });
    }

    const existing = await categoryService.findByCode(data.code, tenantId);
    if (existing) {
      return res.status(409).json({ error: 'Ya existe una categoria con ese codigo' });
    }

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

/**
 * PATCH /api/v1/products/categories/:id
 * Actualiza una categoria
 */
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: UpdateProductCategoryDto = req.body;

    if (data.code) {
      const existing = await categoryService.findByCode(data.code, tenantId);
      if (existing && existing.id !== req.params.id) {
        return res.status(409).json({ error: 'Ya existe una categoria con ese codigo' });
      }
    }

    const category = await categoryService.update(req.params.id, tenantId, data);
    if (!category) {
      return res.status(404).json({ error: 'Categoria no encontrada' });
    }

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

/**
 * DELETE /api/v1/products/categories/:id
 * Elimina una categoria (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 productCount = await categoryService.countProducts(req.params.id, tenantId);
    if (productCount > 0) {
      return res.status(409).json({
        error: `No se puede eliminar la categoria porque tiene ${productCount} productos asociados`
      });
    }

    const deleted = await categoryService.delete(req.params.id, tenantId);
    if (!deleted) {
      return res.status(404).json({ error: 'Categoria no encontrada' });
    }

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

export default router;
