package br.gov.sigefp.rh.service;

import br.gov.sigefp.common.exception.BusinessException;
import br.gov.sigefp.rh.api.dto.AbsenceDTO;
import br.gov.sigefp.rh.api.dto.CreateAbsenceDTO;
import br.gov.sigefp.rh.domain.Absence;
import br.gov.sigefp.rh.domain.Agent;
import br.gov.sigefp.rh.repository.AbsenceRepository;
import br.gov.sigefp.rh.repository.AgentRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
@Transactional
public class AbsenceService {

    private final AbsenceRepository absenceRepository;
    private final AgentRepository agentRepository;

    public AbsenceDTO create(CreateAbsenceDTO dto) {
        Agent agent = agentRepository.findById(dto.getAgentId())
                .orElseThrow(() -> new IllegalArgumentException("Agent not found"));

        if (dto.getEndDate().isBefore(dto.getStartDate())) {
            throw new IllegalArgumentException("Data final deve ser posterior ou igual a data inicial");
        }

        // Calculate days inclusive
        long daysDiff = ChronoUnit.DAYS.between(dto.getStartDate(), dto.getEndDate()) + 1;

        Absence absence = Absence.builder()
                .agent(agent)
                .startDate(dto.getStartDate())
                .endDate(dto.getEndDate())
                .days((int) daysDiff)
                .reason(dto.getReason())
                .justified(dto.isJustified())
                .build();

        Absence saved = absenceRepository.save(absence);
        return toDTO(saved);
    }

    @Transactional(readOnly = true)
    public Page<AbsenceDTO> findByAgent(UUID agentId, Pageable pageable) {
        return absenceRepository.findByAgentId(agentId, pageable)
                .map(this::toDTO);
    }

    @Transactional(readOnly = true)
    public List<AbsenceDTO> findAllByAgent(UUID agentId) {
        return absenceRepository.findByAgentId(agentId).stream()
                .map(this::toDTO)
                .collect(Collectors.toList());
    }

    public void delete(UUID id) {
        Absence absence = absenceRepository.findById(id)
                .orElseThrow(() -> new IllegalArgumentException("Absence not found"));
        if (absence.getDeductedInPayrollRunId() != null) {
            throw new BusinessException("Cannot delete absence already processed in payroll", "ABSENCE_PROCESSED",
                    org.springframework.http.HttpStatus.BAD_REQUEST);
        }
        absenceRepository.delete(absence);
    }

    private AbsenceDTO toDTO(Absence absence) {
        return AbsenceDTO.builder()
                .id(absence.getId())
                .agentId(absence.getAgent().getId())
                .agentName(absence.getAgent().getFullName())
                .startDate(absence.getStartDate())
                .endDate(absence.getEndDate())
                .days(absence.getDays())
                .reason(absence.getReason())
                .justified(absence.isJustified())
                .build();
    }
}
