import { Response, NextFunction } from 'express';
import {
  taxCategoriesService,
  fiscalRegimesService,
  cfdiUsesService,
  paymentMethodsService,
  paymentTypesService,
  withholdingTypesService,
} from './fiscal-catalogs.service.js';
import { PersonType } from './entities/fiscal-regime.entity.js';
import { AuthenticatedRequest } from '../../shared/middleware/auth.middleware.js';

class FiscalController {
  // ========== TAX CATEGORIES ==========
  async getTaxCategories(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const filter = {
        taxNature: req.query.tax_nature as string | undefined,
        active: req.query.active === 'true' ? true : undefined,
      };
      const categories = await taxCategoriesService.findAll(filter);
      res.json({ success: true, data: categories });
    } catch (error) {
      next(error);
    }
  }

  async getTaxCategory(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const category = await taxCategoriesService.findById(req.params.id);
      res.json({ success: true, data: category });
    } catch (error) {
      next(error);
    }
  }

  async getTaxCategoryByCode(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const category = await taxCategoriesService.findByCode(req.params.code);
      if (!category) {
        res.status(404).json({ success: false, message: 'Categoría de impuesto no encontrada' });
        return;
      }
      res.json({ success: true, data: category });
    } catch (error) {
      next(error);
    }
  }

  async getTaxCategoryBySatCode(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const category = await taxCategoriesService.findBySatCode(req.params.satCode);
      if (!category) {
        res.status(404).json({ success: false, message: 'Categoría de impuesto no encontrada' });
        return;
      }
      res.json({ success: true, data: category });
    } catch (error) {
      next(error);
    }
  }

  // ========== FISCAL REGIMES ==========
  async getFiscalRegimes(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const filter = {
        appliesTo: req.query.applies_to as PersonType | undefined,
        active: req.query.active === 'true' ? true : undefined,
      };
      const regimes = await fiscalRegimesService.findAll(filter);
      res.json({ success: true, data: regimes });
    } catch (error) {
      next(error);
    }
  }

  async getFiscalRegime(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const regime = await fiscalRegimesService.findById(req.params.id);
      res.json({ success: true, data: regime });
    } catch (error) {
      next(error);
    }
  }

  async getFiscalRegimeByCode(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const regime = await fiscalRegimesService.findByCode(req.params.code);
      if (!regime) {
        res.status(404).json({ success: false, message: 'Régimen fiscal no encontrado' });
        return;
      }
      res.json({ success: true, data: regime });
    } catch (error) {
      next(error);
    }
  }

  async getFiscalRegimesForPersonType(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const personType = req.params.personType as PersonType;
      const regimes = await fiscalRegimesService.findForPersonType(personType);
      res.json({ success: true, data: regimes });
    } catch (error) {
      next(error);
    }
  }

  // ========== CFDI USES ==========
  async getCfdiUses(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const filter = {
        appliesTo: req.query.applies_to as PersonType | undefined,
        active: req.query.active === 'true' ? true : undefined,
      };
      const uses = await cfdiUsesService.findAll(filter);
      res.json({ success: true, data: uses });
    } catch (error) {
      next(error);
    }
  }

  async getCfdiUse(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const use = await cfdiUsesService.findById(req.params.id);
      res.json({ success: true, data: use });
    } catch (error) {
      next(error);
    }
  }

  async getCfdiUseByCode(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const use = await cfdiUsesService.findByCode(req.params.code);
      if (!use) {
        res.status(404).json({ success: false, message: 'Uso de CFDI no encontrado' });
        return;
      }
      res.json({ success: true, data: use });
    } catch (error) {
      next(error);
    }
  }

  async getCfdiUsesForPersonType(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const personType = req.params.personType as PersonType;
      const uses = await cfdiUsesService.findForPersonType(personType);
      res.json({ success: true, data: uses });
    } catch (error) {
      next(error);
    }
  }

  async getCfdiUsesForRegime(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const uses = await cfdiUsesService.findForRegime(req.params.regimeCode);
      res.json({ success: true, data: uses });
    } catch (error) {
      next(error);
    }
  }

  // ========== PAYMENT METHODS ==========
  async getPaymentMethods(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const filter = {
        requiresBankInfo: req.query.requires_bank_info === 'true' ? true : undefined,
        active: req.query.active === 'true' ? true : undefined,
      };
      const methods = await paymentMethodsService.findAll(filter);
      res.json({ success: true, data: methods });
    } catch (error) {
      next(error);
    }
  }

  async getPaymentMethod(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const method = await paymentMethodsService.findById(req.params.id);
      res.json({ success: true, data: method });
    } catch (error) {
      next(error);
    }
  }

  async getPaymentMethodByCode(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const method = await paymentMethodsService.findByCode(req.params.code);
      if (!method) {
        res.status(404).json({ success: false, message: 'Forma de pago no encontrada' });
        return;
      }
      res.json({ success: true, data: method });
    } catch (error) {
      next(error);
    }
  }

  // ========== PAYMENT TYPES ==========
  async getPaymentTypes(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const filter = {
        active: req.query.active === 'true' ? true : undefined,
      };
      const types = await paymentTypesService.findAll(filter);
      res.json({ success: true, data: types });
    } catch (error) {
      next(error);
    }
  }

  async getPaymentType(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const type = await paymentTypesService.findById(req.params.id);
      res.json({ success: true, data: type });
    } catch (error) {
      next(error);
    }
  }

  async getPaymentTypeByCode(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const type = await paymentTypesService.findByCode(req.params.code);
      if (!type) {
        res.status(404).json({ success: false, message: 'Método de pago no encontrado' });
        return;
      }
      res.json({ success: true, data: type });
    } catch (error) {
      next(error);
    }
  }

  // ========== WITHHOLDING TYPES ==========
  async getWithholdingTypes(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const filter = {
        taxCategoryId: req.query.tax_category_id as string | undefined,
        active: req.query.active === 'true' ? true : undefined,
      };
      const types = await withholdingTypesService.findAll(filter);
      res.json({ success: true, data: types });
    } catch (error) {
      next(error);
    }
  }

  async getWithholdingType(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const type = await withholdingTypesService.findById(req.params.id);
      res.json({ success: true, data: type });
    } catch (error) {
      next(error);
    }
  }

  async getWithholdingTypeByCode(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const type = await withholdingTypesService.findByCode(req.params.code);
      if (!type) {
        res.status(404).json({ success: false, message: 'Tipo de retención no encontrado' });
        return;
      }
      res.json({ success: true, data: type });
    } catch (error) {
      next(error);
    }
  }

  async getWithholdingTypesByCategory(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const types = await withholdingTypesService.findByTaxCategory(req.params.categoryId);
      res.json({ success: true, data: types });
    } catch (error) {
      next(error);
    }
  }
}

export const fiscalController = new FiscalController();
