package com.sino.mci.channel.wecom;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.sino.mci.channel.common.dto.SendMessageRequest;
import com.sino.mci.channel.common.dto.SendMessageResult;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.http.MediaType;
import org.springframework.test.web.client.MockRestServiceServer;
import org.springframework.web.client.RestTemplate;

import java.util.Map;

import static org.junit.jupiter.api.Assertions.*;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.content;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;
import static org.springframework.test.web.client.response.MockRestResponseCreators.withStatus;

class WeComBotSenderTest {

    private RestTemplate restTemplate;
    private MockRestServiceServer server;
    private WeComBotSender sender;

    @BeforeEach
    void setUp() {
        restTemplate = new RestTemplate();
        server = MockRestServiceServer.createServer(restTemplate);
        sender = new WeComBotSender(restTemplate, new ObjectMapper());
    }

    @Test
    void sendRejectsMissingKey() {
        SendMessageRequest request = new SendMessageRequest();
        request.setExtra(null);
        SendMessageResult result = sender.send(request);
        assertFalse(result.isSuccess());
        assertTrue(result.getMessage().contains("webhook key"));
    }

    @Test
    void sendBuildsTextBody() throws Exception {
        server.expect(requestTo("https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=dummy"))
                .andExpect(content().contentType(MediaType.APPLICATION_JSON))
                .andExpect(content().json("{\"msgtype\":\"text\",\"text\":{\"content\":\"hello\"}}"))
                .andRespond(withSuccess("{\"errcode\":0,\"errmsg\":\"ok\"}", MediaType.APPLICATION_JSON));

        SendMessageRequest request = new SendMessageRequest();
        request.setExtra(Map.of("account_id", "dummy"));
        request.setContentType("text");
        request.setContent(Map.of("text", "hello"));
        SendMessageResult result = sender.send(request);
        assertTrue(result.isSuccess(), result.getMessage());
        server.verify();
    }

    @Test
    void sendRejectsUnsupportedContentType() {
        SendMessageRequest request = new SendMessageRequest();
        request.setExtra(Map.of("account_id", "dummy"));
        request.setContentType("image");
        request.setContent(Map.of("media_id", "xxx"));
        SendMessageResult result = sender.send(request);
        assertFalse(result.isSuccess());
        assertTrue(result.getMessage().contains("不支持的消息类型"));
    }

    @Test
    void sendReportsWeComErrorResponse() {
        server.expect(requestTo("https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=dummy"))
                .andRespond(withSuccess("{\"errcode\":40008,\"errmsg\":\"invalid message type\"}", MediaType.APPLICATION_JSON));

        SendMessageRequest request = new SendMessageRequest();
        request.setExtra(Map.of("account_id", "dummy"));
        request.setContentType("text");
        request.setContent(Map.of("text", "hello"));
        SendMessageResult result = sender.send(request);
        assertFalse(result.isSuccess());
        assertTrue(result.getMessage().contains("40008"));
        assertTrue(result.getMessage().contains("invalid message type"));
    }

    @Test
    void sendReportsHttpErrorStatus() {
        server.expect(requestTo("https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=dummy"))
                .andRespond(withStatus(org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR));

        SendMessageRequest request = new SendMessageRequest();
        request.setExtra(Map.of("account_id", "dummy"));
        request.setContentType("text");
        request.setContent(Map.of("text", "hello"));
        SendMessageResult result = sender.send(request);
        assertFalse(result.isSuccess());
        assertTrue(result.getMessage().contains("HTTP 状态"));
    }

    @Test
    void sendUsesCustomWebhookUrl() throws Exception {
        server.expect(requestTo("https://custom.example.com/webhook/send?key=dummy"))
                .andExpect(content().json("{\"msgtype\":\"text\",\"text\":{\"content\":\"hello\"}}"))
                .andRespond(withSuccess("{\"errcode\":0,\"errmsg\":\"ok\"}", MediaType.APPLICATION_JSON));

        SendMessageRequest request = new SendMessageRequest();
        request.setExtra(Map.of("account_id", "dummy", "webhook_url", "https://custom.example.com/webhook/send?key=%s"));
        request.setContentType("text");
        request.setContent(Map.of("text", "hello"));
        SendMessageResult result = sender.send(request);
        assertTrue(result.isSuccess(), result.getMessage());
        server.verify();
    }

    @Test
    void sendUsesCustomWebhookUrlWithoutPlaceholder() throws Exception {
        server.expect(requestTo("https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=REALKEY"))
                .andExpect(content().json("{\"msgtype\":\"text\",\"text\":{\"content\":\"hello\"}}"))
                .andRespond(withSuccess("{\"errcode\":0,\"errmsg\":\"ok\"}", MediaType.APPLICATION_JSON));

        SendMessageRequest request = new SendMessageRequest();
        request.setExtra(Map.of("account_id", "dummy", "webhook_url", "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=REALKEY"));
        request.setContentType("text");
        request.setContent(Map.of("text", "hello"));
        SendMessageResult result = sender.send(request);
        assertTrue(result.isSuccess(), result.getMessage());
        server.verify();
    }

    @Test
    void sendFailsOnUnparseableResponseBody() {
        server.expect(requestTo("https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=dummy"))
                .andRespond(withSuccess("not-json", MediaType.TEXT_PLAIN));

        SendMessageRequest request = new SendMessageRequest();
        request.setExtra(Map.of("account_id", "dummy"));
        request.setContentType("text");
        request.setContent(Map.of("text", "hello"));
        SendMessageResult result = sender.send(request);
        assertFalse(result.isSuccess());
        assertTrue(result.getMessage().contains("无法解析"));
    }
}
