package de.effigenix.infrastructure.shared.web;

import de.effigenix.infrastructure.AbstractIntegrationTest;
import org.junit.jupiter.api.Test;
import static org.hamcrest.Matchers.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

class CountryControllerIntegrationTest extends AbstractIntegrationTest {

    private String validToken() {
        return generateToken("test-user-id", "testuser", "");
    }

    @Test
    void shouldReturnCountriesWithDachFirst() throws Exception {
        mockMvc.perform(get("/api/countries")
                        .header("Authorization", "Bearer " + validToken()))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$", hasSize(greaterThan(200))))
                .andExpect(jsonPath("$[0].code").value("DE"))
                .andExpect(jsonPath("$[1].code").value("AT"))
                .andExpect(jsonPath("$[2].code").value("CH"));
    }

    @Test
    void shouldSearchByName() throws Exception {
        mockMvc.perform(get("/api/countries")
                        .param("q", "deutsch")
                        .header("Authorization", "Bearer " + validToken()))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$[?(@.code == 'DE')]").exists());
    }

    @Test
    void shouldReturnEmptyListForNoMatch() throws Exception {
        mockMvc.perform(get("/api/countries")
                        .param("q", "xyz123nevermatches")
                        .header("Authorization", "Bearer " + validToken()))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$", hasSize(0)));
    }

    @Test
    void shouldReturn401WithoutToken() throws Exception {
        mockMvc.perform(get("/api/countries"))
                .andExpect(status().isUnauthorized());
    }

    @Test
    void shouldSearchByCode() throws Exception {
        mockMvc.perform(get("/api/countries")
                        .param("q", "DE")
                        .header("Authorization", "Bearer " + validToken()))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$[?(@.code == 'DE')]").exists())
                .andExpect(jsonPath("$[?(@.name == 'Deutschland')]").exists());
    }

    @Test
    void shouldReturnResponseWithCodeAndNameFields() throws Exception {
        mockMvc.perform(get("/api/countries")
                        .param("q", "deutsch")
                        .header("Authorization", "Bearer " + validToken()))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$[0].code").isString())
                .andExpect(jsonPath("$[0].name").isString());
    }

    @Test
    void shouldReturn401WithExpiredToken() throws Exception {
        mockMvc.perform(get("/api/countries")
                        .header("Authorization", "Bearer " + generateExpiredToken("test-user-id", "testuser")))
                .andExpect(status().isUnauthorized());
    }

    @Test
    void shouldReturnAllCountriesWithWhitespaceQuery() throws Exception {
        mockMvc.perform(get("/api/countries")
                        .param("q", "   ")
                        .header("Authorization", "Bearer " + validToken()))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$", hasSize(greaterThan(200))));
    }

    @Test
    void searchResultsShouldPrioritizeDach() throws Exception {
        mockMvc.perform(get("/api/countries")
                        .param("q", "land")
                        .header("Authorization", "Bearer " + validToken()))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$[0].code").value("DE"));
    }
}
