package br.gov.sigefp.budget.service;

import br.gov.sigefp.budget.api.dto.FiscalYearDTO;
import br.gov.sigefp.budget.domain.FiscalYear;
import br.gov.sigefp.budget.repository.BudgetExecutionRepository;
import br.gov.sigefp.budget.repository.FiscalYearRepository;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import java.util.Optional;
import java.util.UUID;

import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.*;

@ExtendWith(MockitoExtension.class)
class FiscalYearServiceTest {

    @Mock
    private FiscalYearRepository fiscalYearRepository;
    @Mock
    private BudgetExecutionRepository budgetExecutionRepository;

    @InjectMocks
    private FiscalYearService fiscalYearService;

    @Test
    @DisplayName("Should use efficient COUNT query to check pending commitments")
    void close_ShouldUseCountQuery() {
        UUID id = UUID.randomUUID();
        FiscalYear fiscalYear = FiscalYear.builder().id(id).status("OPEN").build();

        when(fiscalYearRepository.findById(id)).thenReturn(Optional.of(fiscalYear));
        when(budgetExecutionRepository.countByFiscalYearIdAndMovementType(id, "COMMITMENT")).thenReturn(0L); // No
                                                                                                             // pending
        when(fiscalYearRepository.save(any(FiscalYear.class))).thenReturn(fiscalYear);

        fiscalYearService.close(id);

        verify(budgetExecutionRepository).countByFiscalYearIdAndMovementType(id, "COMMITMENT");
        verify(budgetExecutionRepository, never()).findExecutionsByFiscalYearId(any()); // Ensure list is NOT loaded
    }

    @Test
    @DisplayName("Should block closing if pending commitments exist")
    void close_ShouldBlockIfPending() {
        UUID id = UUID.randomUUID();
        FiscalYear fiscalYear = FiscalYear.builder().id(id).status("OPEN").build();

        when(fiscalYearRepository.findById(id)).thenReturn(Optional.of(fiscalYear));
        when(budgetExecutionRepository.countByFiscalYearIdAndMovementType(id, "COMMITMENT")).thenReturn(5L); // 5
                                                                                                             // pending

        Exception exception = assertThrows(IllegalArgumentException.class, () -> fiscalYearService.close(id));

        assertTrue(exception.getMessage().contains("existem movimentos em aberto"));
        verify(fiscalYearRepository, never()).save(any());
    }
}
