package com.corewing.app.util;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

/**
 * 钉钉机器人推送工具类
 */
@Slf4j
@Component
public class DingTalkUtil {

    @Value("${dingtalk.webhook:}")
    private String webhook;

    @Value("${dingtalk.secret:}")
    private String secret;

    private static final ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 发送文本消息到钉钉
     *
     * @param content 消息内容
     * @return 是否发送成功
     */
    public boolean sendTextMessage(String content) {
        return sendTextMessage(content, null);
    }

    /**
     * 发送文本消息到钉钉
     *
     * @param content 消息内容
     * @param atMobiles 需要@的手机号列表
     * @return 是否发送成功
     */
    public boolean sendTextMessage(String content, String[] atMobiles) {
        if (webhook == null || webhook.trim().isEmpty()) {
            log.warn("钉钉 Webhook 未配置，跳过消息推送");
            return false;
        }

        try {
            Map<String, Object> message = new HashMap<>();
            message.put("msgtype", "text");

            Map<String, Object> text = new HashMap<>();
            text.put("content", content);
            message.put("text", text);

            // @人员配置
            if (atMobiles != null && atMobiles.length > 0) {
                Map<String, Object> at = new HashMap<>();
                at.put("atMobiles", atMobiles);
                at.put("isAtAll", false);
                message.put("at", at);
            }

            return sendRequest(message);
        } catch (Exception e) {
            log.error("发送钉钉文本消息失败: {}", e.getMessage(), e);
            return false;
        }
    }

    /**
     * 发送 Markdown 消息到钉钉
     *
     * @param title 消息标题
     * @param text Markdown 内容
     * @return 是否发送成功
     */
    public boolean sendMarkdownMessage(String title, String text) {
        return sendMarkdownMessage(title, text, null);
    }

    /**
     * 发送 Markdown 消息到钉钉
     *
     * @param title 消息标题
     * @param text Markdown 内容
     * @param atMobiles 需要@的手机号列表
     * @return 是否发送成功
     */
    public boolean sendMarkdownMessage(String title, String text, String[] atMobiles) {
        if (webhook == null || webhook.trim().isEmpty()) {
            log.warn("钉钉 Webhook 未配置，跳过消息推送");
            return false;
        }

        try {
            Map<String, Object> message = new HashMap<>();
            message.put("msgtype", "markdown");

            Map<String, Object> markdown = new HashMap<>();
            markdown.put("title", title);
            markdown.put("text", text);
            message.put("markdown", markdown);

            // @人员配置
            if (atMobiles != null && atMobiles.length > 0) {
                Map<String, Object> at = new HashMap<>();
                at.put("atMobiles", atMobiles);
                at.put("isAtAll", false);
                message.put("at", at);
            }

            return sendRequest(message);
        } catch (Exception e) {
            log.error("发送钉钉 Markdown 消息失败: {}", e.getMessage(), e);
            return false;
        }
    }

    /**
     * 生成钉钉签名
     *
     * @param timestamp 时间戳
     * @return 签名
     */
    private String generateSign(long timestamp) throws Exception {
        String stringToSign = timestamp + "\n" + secret;
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
        byte[] signData = mac.doFinal(stringToSign.getBytes(StandardCharsets.UTF_8));
        return URLEncoder.encode(Base64.getEncoder().encodeToString(signData), "UTF-8");
    }

    /**
     * 发送 HTTP 请求到钉钉机器人
     *
     * @param message 消息体
     * @return 是否发送成功
     */
    private boolean sendRequest(Map<String, Object> message) {
        HttpURLConnection connection = null;
        try {
            String finalWebhook = webhook;

            // 如果配置了 secret，需要添加签名
            if (secret != null && !secret.trim().isEmpty()) {
                long timestamp = System.currentTimeMillis();
                String sign = generateSign(timestamp);
                finalWebhook = webhook + "&timestamp=" + timestamp + "&sign=" + sign;
                log.info("使用加签模式，timestamp: {}", timestamp);
            }

            URL url = new URL(finalWebhook);
            connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("POST");
            connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
            connection.setDoOutput(true);
            connection.setConnectTimeout(5000);
            connection.setReadTimeout(5000);

            // 发送请求
            String jsonMessage = objectMapper.writeValueAsString(message);
            log.info("发送钉钉消息: {}", jsonMessage);

            try (OutputStream os = connection.getOutputStream()) {
                byte[] input = jsonMessage.getBytes(StandardCharsets.UTF_8);
                os.write(input, 0, input.length);
            }

            // 读取响应
            int responseCode = connection.getResponseCode();

            // 读取响应体（包含错误信息）
            java.io.BufferedReader br = new java.io.BufferedReader(
                new java.io.InputStreamReader(
                    responseCode >= 400 ? connection.getErrorStream() : connection.getInputStream(),
                    StandardCharsets.UTF_8
                )
            );
            StringBuilder response = new StringBuilder();
            String responseLine;
            while ((responseLine = br.readLine()) != null) {
                response.append(responseLine.trim());
            }
            br.close();

            if (responseCode == HttpURLConnection.HTTP_OK) {
                log.info("钉钉消息推送成功, 响应: {}", response.toString());
                return true;
            } else {
                log.error("钉钉消息推送失败, HTTP 状态码: {}, 响应: {}", responseCode, response.toString());
                return false;
            }
        } catch (Exception e) {
            log.error("钉钉消息推送异常: {}", e.getMessage(), e);
            return false;
        } finally {
            if (connection != null) {
                connection.disconnect();
            }
        }
    }
}
