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 lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.client.HttpStatusCodeException;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.Map;

@Slf4j
@Component
public class WeComBotSender {

    private static final String DEFAULT_WEBHOOK_URL = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=%s";
    private static final int CONNECT_TIMEOUT_MS = 5000;
    private static final int READ_TIMEOUT_MS = 10000;

    private final RestTemplate restTemplate;
    private final ObjectMapper objectMapper;

    public WeComBotSender() {
        this.restTemplate = createRestTemplate();
        this.objectMapper = new ObjectMapper();
    }

    public WeComBotSender(RestTemplate restTemplate, ObjectMapper objectMapper) {
        this.restTemplate = restTemplate;
        this.objectMapper = objectMapper;
    }

    public SendMessageResult send(SendMessageRequest request) {
        SendMessageResult result = new SendMessageResult();
        String key = getString(request.getExtra(), "account_id");
        if (key == null || key.isBlank()) {
            result.setSuccess(false);
            result.setMessage("企微群机器人缺少 webhook key");
            return result;
        }

        String contentType = request.getContentType() == null ? "text" : request.getContentType().toLowerCase();
        Map<String, Object> body = buildBody(contentType, request.getContent());
        if (body == null) {
            result.setSuccess(false);
            result.setMessage("不支持的消息类型: " + contentType);
            return result;
        }

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<Map<String, Object>> entity = new HttpEntity<>(body, headers);

        try {
            String url = resolveWebhookUrl(request.getExtra(), key);
            ResponseEntity<String> response = restTemplate.postForEntity(url, entity, String.class);
            Map<String, Object> responseBody = parseResponseBody(response.getBody());
            if (responseBody == null) {
                result.setSuccess(false);
                result.setMessage("企微群机器人返回无法解析的响应");
                return result;
            }
            int errcode = parseInt(responseBody.get("errcode"));
            if (errcode != 0) {
                result.setSuccess(false);
                String errmsg = getString(responseBody, "errmsg");
                result.setMessage("企微群机器人发送失败: [" + errcode + "] " + errmsg);
                return result;
            }
            result.setSuccess(true);
        } catch (HttpStatusCodeException e) {
            log.warn("[WeComBot] 发送失败，HTTP 状态: {}", e.getStatusCode(), e);
            result.setSuccess(false);
            result.setMessage("企微群机器人发送失败，HTTP 状态: " + e.getStatusCode());
        } catch (Exception e) {
            log.warn("[WeComBot] 发送失败", e);
            result.setSuccess(false);
            result.setMessage("企微群机器人发送失败: " + e.getMessage());
        }
        return result;
    }

    private String resolveWebhookUrl(Map<String, Object> extra, String key) {
        String customUrl = getString(extra, "webhook_url");
        if (customUrl != null && !customUrl.isBlank()) {
            if (customUrl.contains("%s")) {
                return customUrl.replaceFirst("%s", key);
            }
            return customUrl;
        }
        return String.format(DEFAULT_WEBHOOK_URL, key);
    }

    private Map<String, Object> parseResponseBody(String body) {
        if (body == null || body.isBlank()) {
            return null;
        }
        try {
            return objectMapper.readValue(body, Map.class);
        } catch (Exception e) {
            log.warn("[WeComBot] 解析响应失败: {}", body, e);
            return null;
        }
    }

    private int parseInt(Object value) {
        if (value == null) {
            return 0;
        }
        if (value instanceof Number number) {
            return number.intValue();
        }
        try {
            return Integer.parseInt(value.toString());
        } catch (NumberFormatException e) {
            return 0;
        }
    }

    private RestTemplate createRestTemplate() {
        SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
        factory.setConnectTimeout(CONNECT_TIMEOUT_MS);
        factory.setReadTimeout(READ_TIMEOUT_MS);
        return new RestTemplate(factory);
    }

    private Map<String, Object> buildBody(String contentType, Map<String, Object> content) {
        Map<String, Object> body = new HashMap<>();
        switch (contentType) {
            case "text" -> {
                body.put("msgtype", "text");
                Map<String, Object> text = new HashMap<>();
                text.put("content", getString(content, "text"));
                body.put("text", text);
            }
            case "markdown" -> {
                body.put("msgtype", "markdown");
                Map<String, Object> markdown = new HashMap<>();
                markdown.put("content", getString(content, "text"));
                body.put("markdown", markdown);
            }
            default -> {
                return null;
            }
        }
        return body;
    }

    private String getString(Map<String, Object> map, String key) {
        if (map == null) {
            return null;
        }
        Object value = map.get(key);
        return value == null ? null : value.toString();
    }
}
