package br.gov.sigefp.rh.service;

import br.gov.sigefp.rh.domain.GlobalDeductionRule;
import br.gov.sigefp.rh.domain.TaxBracket;
import br.gov.sigefp.rh.repository.GlobalDeductionRuleRepository;
import br.gov.sigefp.rh.repository.TaxBracketRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import br.gov.sigefp.rh.repository.DeductionTypeRepository;
import java.util.List;
import java.util.UUID;
import java.time.LocalDate;

/**
 * Serviço para gestão de regras tributárias e escalões.
 */
@Service
@RequiredArgsConstructor
@Transactional
public class TaxService {

    private final GlobalDeductionRuleRepository globalDeductionRuleRepository;
    private final TaxBracketRepository taxBracketRepository;
    private final DeductionTypeRepository deductionTypeRepository;

    // --- Deduction Types ---

    @org.springframework.security.access.prepost.PreAuthorize("hasRole('HR_CONFIG')")
    public br.gov.sigefp.rh.domain.DeductionType saveDeductionType(br.gov.sigefp.rh.domain.DeductionType type) {
        if (type.getId() == null) {
            // New: Ensure Code Unique (Repository should handle or we check)
        }
        return deductionTypeRepository.save(type);
    }

    public void toggleDeductionTypeStatus(UUID id) {
        br.gov.sigefp.rh.domain.DeductionType type = deductionTypeRepository.findById(id)
                .orElseThrow(() -> new br.gov.sigefp.common.exception.ResourceNotFoundException("Tipo não encontrado"));
        type.setActive(!Boolean.TRUE.equals(type.getActive()));
        deductionTypeRepository.save(type);
    }

    public List<GlobalDeductionRule> findAllRules() {
        return globalDeductionRuleRepository.findAll();
    }

    @org.springframework.security.access.prepost.PreAuthorize("hasRole('HR_CONFIG')")
    public GlobalDeductionRule saveRule(GlobalDeductionRule rule) {
        // P13: Validação de Sobreposição de Regras Globais
        if (rule.getDeductionType() == null) {
            throw new IllegalArgumentException("O tipo de desconto é obrigatório.");
        }

        // Data fim padrão se nula (opcional, mas ajuda na consulta)
        LocalDate start = rule.getValidFrom();
        LocalDate end = rule.getValidTo() != null ? rule.getValidTo() : LocalDate.of(2099, 12, 31);

        List<GlobalDeductionRule> overlaps = globalDeductionRuleRepository.findOverlappingRules(
                rule.getDeductionType().getId(), start, end);

        for (GlobalDeductionRule existing : overlaps) {
            if (!existing.getId().equals(rule.getId())) {
                throw new br.gov.sigefp.common.exception.BusinessException(
                        "Sobreposição de datas detectada com a regra ID: " + existing.getId(),
                        "RULE_OVERLAP", org.springframework.http.HttpStatus.BAD_REQUEST);
            }
        }

        return globalDeductionRuleRepository.save(rule);
    }

    public void deleteRule(UUID id) {
        globalDeductionRuleRepository.deleteById(id);
    }

    public List<TaxBracket> findAllBrackets() {
        return taxBracketRepository.findAll();
    }

    @org.springframework.security.access.prepost.PreAuthorize("hasRole('HR_CONFIG')")
    public TaxBracket saveBracket(TaxBracket bracket) {
        // P14: Validação de Sobreposição de Escalões
        if (bracket.getDeductionType() == null) {
            throw new IllegalArgumentException("O tipo de desconto é obrigatório.");
        }

        LocalDate start = bracket.getValidFrom();
        LocalDate end = bracket.getValidTo() != null ? bracket.getValidTo() : LocalDate.of(2099, 12, 31);
        java.math.BigDecimal lower = bracket.getLowerLimit();
        // Se upper for null, tratar como infinito para validação
        java.math.BigDecimal upper = bracket.getUpperLimit() != null ? bracket.getUpperLimit()
                : new java.math.BigDecimal("999999999");

        List<TaxBracket> overlaps = taxBracketRepository.findOverlappingBrackets(
                bracket.getDeductionType().getId(), start, end, lower, upper);

        for (TaxBracket existing : overlaps) {
            if (!existing.getId().equals(bracket.getId())) {
                throw new br.gov.sigefp.common.exception.BusinessException(
                        "Sobreposição de escalões detectada com o ID: " + existing.getId(),
                        "BRACKET_OVERLAP", org.springframework.http.HttpStatus.BAD_REQUEST);
            }
        }

        return taxBracketRepository.save(bracket);
    }

    public void deleteBracket(UUID id) {
        taxBracketRepository.deleteById(id);
    }

    public List<br.gov.sigefp.rh.domain.DeductionType> findAllDeductionTypes() {
        return deductionTypeRepository.findAll();
    }
}
