package kr.itn.itnhub.mattermost;

import com.github.tomakehurst.wiremock.WireMockServer;
import kr.itn.itnhub.config.MattermostProperties;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import static com.github.tomakehurst.wiremock.client.WireMock.*;
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

class MattermostRestClientTest {

    private WireMockServer server;
    private MattermostRestClient client;

    @BeforeEach
    void setUp() {
        server = new WireMockServer(options().dynamicPort());
        server.start();

        MattermostProperties props = new MattermostProperties(
                "http://localhost:" + server.port(),
                "test-token",
                "team123",
                "문정원",
                "법률검토");

        client = new MattermostRestClient(props);
    }

    @AfterEach
    void tearDown() {
        server.stop();
    }

    @Test
    void 내부명으로_채널을_찾으면_id를_돌려준다() {
        server.stubFor(get(urlEqualTo("/api/v4/teams/team123/channels/name/org-001-mj"))
                .willReturn(okJson("{\"id\":\"chan001mj\",\"name\":\"org-001-mj\"}")));

        assertThat(client.findChannelIdByInternalName("org-001-mj"))
                .contains("chan001mj");
    }

    @Test
    void 내부명으로_채널이_없으면_빈값이다() {
        server.stubFor(get(urlEqualTo("/api/v4/teams/team123/channels/name/org-999-mj"))
                .willReturn(aResponse().withStatus(404)));

        assertThat(client.findChannelIdByInternalName("org-999-mj")).isEmpty();
    }

    @Test
    void 토큰을_Authorization_헤더로_보낸다() {
        server.stubFor(get(urlEqualTo("/api/v4/teams/team123/channels/name/org-001-mj"))
                .willReturn(okJson("{\"id\":\"chan001mj\"}")));

        client.findChannelIdByInternalName("org-001-mj");

        server.verify(getRequestedFor(urlEqualTo("/api/v4/teams/team123/channels/name/org-001-mj"))
                .withHeader("Authorization", equalTo("Bearer test-token")));
    }

    @Test
    void 표시명으로_내_채널목록에서_id를_찾는다() {
        server.stubFor(get(urlPathEqualTo("/api/v4/users/me/teams/team123/channels"))
                .willReturn(okJson("""
                        [
                          {"id":"aaa","display_name":"001_국제방송교류재단 (문정원)"},
                          {"id":"bbb","display_name":"001_국제방송교류재단 (법률검토)"}
                        ]
                        """)));

        assertThat(client.findChannelIdByDisplayName("001_국제방송교류재단 (법률검토)"))
                .contains("bbb");
        assertThat(client.findChannelIdByDisplayName("002_없는기관 (문정원)"))
                .isEmpty();
    }

    @Test
    void 비공개_채널을_생성하고_id를_돌려준다() {
        server.stubFor(post(urlEqualTo("/api/v4/channels"))
                .willReturn(okJson("{\"id\":\"newchan\"}")));

        String id = client.createPrivateChannel("org-002-mj", "002_세종학당재단 (문정원)");

        assertThat(id).isEqualTo("newchan");

        server.verify(postRequestedFor(urlEqualTo("/api/v4/channels"))
                .withRequestBody(matchingJsonPath("$.team_id", equalTo("team123")))
                .withRequestBody(matchingJsonPath("$.name", equalTo("org-002-mj")))
                .withRequestBody(matchingJsonPath("$.display_name",
                        equalTo("002_세종학당재단 (문정원)")))
                .withRequestBody(matchingJsonPath("$.type", equalTo("P"))));
    }

    @Test
    void 서버가_오류를_주면_MattermostException을_던진다() {
        server.stubFor(post(urlEqualTo("/api/v4/channels"))
                .willReturn(aResponse().withStatus(500).withBody("boom")));

        assertThatThrownBy(() -> client.createPrivateChannel("org-003-mj", "003_기관 (문정원)"))
                .isInstanceOf(MattermostException.class);
    }
}
