package dev.lions.user.manager.resource;

import dev.lions.user.manager.dto.audit.AuditLogDTO;
import dev.lions.user.manager.dto.common.CountDTO;
import dev.lions.user.manager.enums.audit.TypeActionAudit;
import dev.lions.user.manager.service.AuditService;
import jakarta.ws.rs.core.Response;
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.Collections;
import java.util.List;
import java.util.Map;

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

@ExtendWith(MockitoExtension.class)
class AuditResourceTest {

    @Mock
    AuditService auditService;

    @InjectMocks
    AuditResource auditResource;

    @Test
    void testSearchLogs() {
        List<AuditLogDTO> logs = Collections.singletonList(
                AuditLogDTO.builder().acteurUsername("admin").typeAction(TypeActionAudit.USER_CREATE).build());
        when(auditService.findByActeur(eq("admin"), any(), any(), eq(0), eq(50))).thenReturn(logs);

        List<AuditLogDTO> result = auditResource.searchLogs("admin", null, null, null, null, null, 0, 50);

        assertEquals(logs, result);
    }

    @Test
    void testGetLogsByActor() {
        List<AuditLogDTO> logs = Collections.singletonList(
                AuditLogDTO.builder().acteurUsername("admin").build());
        when(auditService.findByActeur(eq("admin"), isNull(), isNull(), eq(0), eq(100))).thenReturn(logs);

        List<AuditLogDTO> result = auditResource.getLogsByActor("admin", 100);

        assertEquals(logs, result);
    }

    @Test
    void testGetLogsByResource() {
        List<AuditLogDTO> logs = Collections.emptyList();
        when(auditService.findByRessource(eq("USER"), eq("1"), any(), any(), eq(0), eq(100)))
                .thenReturn(logs);

        List<AuditLogDTO> result = auditResource.getLogsByResource("USER", "1", 100);

        assertEquals(logs, result);
    }

    @Test
    void testGetLogsByAction() {
        List<AuditLogDTO> logs = Collections.emptyList();
        when(auditService.findByTypeAction(eq(TypeActionAudit.USER_CREATE), eq("master"), any(), any(), eq(0), eq(100)))
                .thenReturn(logs);

        List<AuditLogDTO> result = auditResource.getLogsByAction(TypeActionAudit.USER_CREATE, null, null, 100);

        assertEquals(logs, result);
    }

    @Test
    void testGetActionStatistics() {
        Map<TypeActionAudit, Long> stats = Map.of(TypeActionAudit.USER_CREATE, 10L);
        when(auditService.countByActionType(eq("master"), any(), any())).thenReturn(stats);

        Map<TypeActionAudit, Long> result = auditResource.getActionStatistics(null, null);

        assertEquals(stats, result);
    }

    @Test
    void testGetUserActivityStatistics() {
        Map<String, Long> stats = Map.of("admin", 100L);
        when(auditService.countByActeur(eq("master"), any(), any())).thenReturn(stats);

        Map<String, Long> result = auditResource.getUserActivityStatistics(null, null);

        assertEquals(stats, result);
    }

    @Test
    void testGetFailureCount() {
        Map<String, Long> successVsFailure = Map.of("failure", 5L, "success", 100L);
        when(auditService.countSuccessVsFailure(eq("master"), any(), any())).thenReturn(successVsFailure);

        CountDTO result = auditResource.getFailureCount(null, null);

        assertEquals(5L, result.getCount());
    }

    @Test
    void testGetSuccessCount() {
        Map<String, Long> successVsFailure = Map.of("failure", 5L, "success", 100L);
        when(auditService.countSuccessVsFailure(eq("master"), any(), any())).thenReturn(successVsFailure);

        CountDTO result = auditResource.getSuccessCount(null, null);

        assertEquals(100L, result.getCount());
    }

    @Test
    void testExportLogsToCSV() {
        when(auditService.exportToCSV(eq("master"), any(), any())).thenReturn("csv,data");

        Response response = auditResource.exportLogsToCSV(null, null);

        assertEquals(200, response.getStatus());
        assertEquals("csv,data", response.getEntity());
    }

    @Test
    void testPurgeOldLogs() {
        doNothing().when(auditService).purgeOldLogs(any());

        auditResource.purgeOldLogs(90);

        verify(auditService).purgeOldLogs(any());
    }
}
