package org.raddatz.familienarchiv.document.transcription;

import org.junit.jupiter.api.Test;
import org.raddatz.familienarchiv.security.SecurityConfig;
import org.raddatz.familienarchiv.document.transcription.TranscriptionQueueItemDTO;
import org.raddatz.familienarchiv.document.transcription.TranscriptionWeeklyStatsDTO;
import org.raddatz.familienarchiv.document.DocumentRepository;
import org.raddatz.familienarchiv.person.PersonRepository;
import org.raddatz.familienarchiv.security.PermissionAspect;
import org.raddatz.familienarchiv.user.CustomUserDetailsService;
import org.raddatz.familienarchiv.document.transcription.TranscriptionQueueService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.aop.AopAutoConfiguration;
import org.springframework.boot.webmvc.test.autoconfigure.WebMvcTest;
import org.springframework.context.annotation.Import;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
import org.springframework.test.web.servlet.MockMvc;

import org.raddatz.familienarchiv.audit.ActivityActorDTO;

import java.time.LocalDate;
import java.util.List;
import java.util.UUID;

import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@WebMvcTest(TranscriptionQueueController.class)
@Import({SecurityConfig.class, PermissionAspect.class, AopAutoConfiguration.class})
class TranscriptionQueueControllerTest {

    @Autowired MockMvc mockMvc;

    @MockitoBean TranscriptionQueueService transcriptionQueueService;
    @MockitoBean DocumentRepository documentRepository;
    @MockitoBean PersonRepository personRepository;
    @MockitoBean CustomUserDetailsService customUserDetailsService;

    private static final TranscriptionQueueItemDTO ITEM = new TranscriptionQueueItemDTO(
            UUID.fromString("00000000-0000-0000-0000-000000000001"),
            "Testbrief",
            LocalDate.of(1920, 6, 15),
            3, 1, 0,
            List.of(new ActivityActorDTO("TR", "#a6dad8", "Test Raddatz")),
            false
    );

    private static final TranscriptionWeeklyStatsDTO STATS = new TranscriptionWeeklyStatsDTO(2L, 5L);

    // ─── segmentation-queue ───────────────────────────────────────────────────

    @Test
    void getSegmentationQueue_returns401_whenUnauthenticated() throws Exception {
        mockMvc.perform(get("/api/transcription/segmentation-queue"))
                .andExpect(status().isUnauthorized());
    }

    @Test
    @WithMockUser
    void getSegmentationQueue_returns403_whenNoReadAllPermission() throws Exception {
        mockMvc.perform(get("/api/transcription/segmentation-queue"))
                .andExpect(status().isForbidden());
    }

    @Test
    @WithMockUser(authorities = "READ_ALL")
    void getSegmentationQueue_returns200_withItems() throws Exception {
        when(transcriptionQueueService.getSegmentationQueue()).thenReturn(List.of(ITEM));

        mockMvc.perform(get("/api/transcription/segmentation-queue"))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$[0].title").value("Testbrief"))
                .andExpect(jsonPath("$[0].annotationCount").value(3));
    }

    // ─── transcription-queue ──────────────────────────────────────────────────

    @Test
    void getTranscriptionQueue_returns401_whenUnauthenticated() throws Exception {
        mockMvc.perform(get("/api/transcription/transcription-queue"))
                .andExpect(status().isUnauthorized());
    }

    @Test
    @WithMockUser
    void getTranscriptionQueue_returns403_whenNoReadAllPermission() throws Exception {
        mockMvc.perform(get("/api/transcription/transcription-queue"))
                .andExpect(status().isForbidden());
    }

    @Test
    @WithMockUser(authorities = "READ_ALL")
    void getTranscriptionQueue_returns200_withItems() throws Exception {
        when(transcriptionQueueService.getTranscriptionQueue()).thenReturn(List.of(ITEM));

        mockMvc.perform(get("/api/transcription/transcription-queue"))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$[0].title").value("Testbrief"));
    }

    // ─── ready-to-read ────────────────────────────────────────────────────────

    @Test
    void getReadyToRead_returns401_whenUnauthenticated() throws Exception {
        mockMvc.perform(get("/api/transcription/ready-to-read"))
                .andExpect(status().isUnauthorized());
    }

    @Test
    @WithMockUser
    void getReadyToRead_returns403_whenNoReadAllPermission() throws Exception {
        mockMvc.perform(get("/api/transcription/ready-to-read"))
                .andExpect(status().isForbidden());
    }

    @Test
    @WithMockUser(authorities = "READ_ALL")
    void getReadyToRead_returns200_withItems() throws Exception {
        when(transcriptionQueueService.getReadyToReadQueue()).thenReturn(List.of(ITEM));

        mockMvc.perform(get("/api/transcription/ready-to-read"))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$[0].reviewedBlockCount").value(0));
    }

    // ─── weekly-stats ─────────────────────────────────────────────────────────

    @Test
    void getWeeklyStats_returns401_whenUnauthenticated() throws Exception {
        mockMvc.perform(get("/api/transcription/weekly-stats"))
                .andExpect(status().isUnauthorized());
    }

    @Test
    @WithMockUser
    void getWeeklyStats_returns403_whenNoReadAllPermission() throws Exception {
        mockMvc.perform(get("/api/transcription/weekly-stats"))
                .andExpect(status().isForbidden());
    }

    @Test
    @WithMockUser(authorities = "READ_ALL")
    void getWeeklyStats_returns200_withStats() throws Exception {
        when(transcriptionQueueService.getWeeklyStats()).thenReturn(STATS);

        mockMvc.perform(get("/api/transcription/weekly-stats"))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.segmentationCount").value(2))
                .andExpect(jsonPath("$.transcriptionCount").value(5));
    }
}
