package com.njcn.product.event.transientes.utils;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.SM3;
import cn.hutool.json.JSONObject;
import com.njcn.common.pojo.enums.response.CommonResponseEnum;
import com.njcn.common.pojo.exception.BusinessException;
import com.njcn.product.event.transientes.pojo.dto.MsgDTO;
import com.njcn.product.event.transientes.pojo.dto.SmsResponseDTO;
import com.njcn.product.event.transientes.pojo.dto.SmsSendDTO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author: cdf
 * @CreateTime: 2025-10-15
 * @Description: 短信工具
 */
@Component
@Slf4j
@RequiredArgsConstructor
public class SmsUtils {

    private final RestTemplate restTemplate;
    // 最大重试次数
    private static final int MAX_RETRY_COUNT = 2;
    //短信平台成功返回码
    private static final String SUCCESS_CODE = "0";
    //短信平台业务码
    private static final String SERVICE_CODE = "01001101";

    @Value("${smsServer.info}")
    private String smsServer;

    @Value("${smsServer.account}")
    private String account;

    @Value("${smsServer.password}")
    private String password;


    /**
     * 发送短信给用户
     *
     * @param itemList 短信内容列表
     * @return 发送结果列表
     */
    public List<SmsResponseDTO.SmsItem> sendSmSToUser(List<SmsSendDTO.ItemInner> itemList) {
        if (CollUtil.isEmpty(itemList)) {
            log.info("短信发送列表为空");
            return Collections.emptyList();
        }
        return sendSmSToUserWithRetry(itemList, MAX_RETRY_COUNT);
    }


    /**
     * 带重试机制的短信发送
     *
     * @param itemList  短信内容列表
     * @param retryCount 剩余重试次数
     * @return 发送结果列表
     */
    private List<SmsResponseDTO.SmsItem> sendSmSToUserWithRetry(List<SmsSendDTO.ItemInner> itemList, int retryCount) {
        if (retryCount <= 0) {
            log.error("短信发送重试次数耗尽，剩余{}条短信发送失败", itemList.size());
            return buildFailedResponse(itemList);
        }

        try {
            SmsSendDTO smsSendDTO = buildSmsRequest(itemList);
            ResponseEntity<SmsResponseDTO> response = executeSmsRequest(smsSendDTO);
            return processSmsResponse(response, itemList, retryCount);

        } catch (RestClientException e) {
            log.error("第{}次短信发送网络异常，剩余重试次数: {}",
                    MAX_RETRY_COUNT - retryCount + 1, retryCount - 1, e);
            return sendSmSToUserWithRetry(itemList, retryCount - 1);
        } catch (Exception e) {
            log.error("第{}次短信发送系统异常，剩余重试次数: {}",
                    MAX_RETRY_COUNT - retryCount + 1, retryCount - 1, e);
            return sendSmSToUserWithRetry(itemList, retryCount - 1);
        }
    }

    /**
     * 构建短信请求参数
     */
    private SmsSendDTO buildSmsRequest(List<SmsSendDTO.ItemInner> itemList) {
        String nowTime = LocalDateTime.now().format(
                DateTimeFormatter.ofPattern(DatePattern.PURE_DATETIME_PATTERN));
        String sm3Hash = new SM3().digestHex(account + password + nowTime);

        SmsSendDTO smsSendDTO = new SmsSendDTO();
        smsSendDTO.setServiceCode(SERVICE_CODE);
        smsSendDTO.setAccount(account);
        smsSendDTO.setToken(sm3Hash);
        smsSendDTO.setTs(nowTime);
        smsSendDTO.setItems(itemList);
        log.info("短信请求实体{}", smsSendDTO);

        return smsSendDTO;
    }

    /**
     * 执行短信请求
     */
    private ResponseEntity<SmsResponseDTO> executeSmsRequest(SmsSendDTO smsSendDTO) {
        String url = smsServer + "/sms/msg";
        log.info("调用短信接口: {}", url);

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));

        String requestBody = new JSONObject(smsSendDTO).toString();
        HttpEntity<String> requestEntity = new HttpEntity<>(requestBody, headers);
        return restTemplate.exchange(url, HttpMethod.POST, requestEntity, SmsResponseDTO.class);
    }


    /**
     * 处理短信响应
     */
    private List<SmsResponseDTO.SmsItem> processSmsResponse(
            ResponseEntity<SmsResponseDTO> response,
            List<SmsSendDTO.ItemInner> originalList,
            int retryCount) {

        // 检查HTTP状态码
        if (response.getStatusCode() != HttpStatus.OK) {
            log.error("短信接口HTTP状态码异常: {}", response.getStatusCode());
            return sendSmSToUserWithRetry(originalList, retryCount - 1);
        }

        // 检查响应体
        SmsResponseDTO smsResponse = response.getBody();
        if (smsResponse == null) {
            log.error("短信接口返回体为空");
            return sendSmSToUserWithRetry(originalList, retryCount - 1);
        }

        // 检查业务状态码
        if (!SUCCESS_CODE.equals(smsResponse.getCode())) {
            log.error("短信发送业务失败: {} - {}", smsResponse.getCode(), smsResponse.getMessage());
            return sendSmSToUserWithRetry(originalList, retryCount - 1);
        }

        log.info("短信发送接口调用成功，batchId: {}, 发送条数: {}",
                smsResponse.getBatchId(), smsResponse.getItems().size());

        // 处理部分失败的情况
        return handlePartialFailures(smsResponse, originalList);
    }

    /**
     * 处理部分短信发送失败的情况
     */
    private List<SmsResponseDTO.SmsItem> handlePartialFailures(
            SmsResponseDTO smsResponse,
            List<SmsSendDTO.ItemInner> originalList) {

        List<SmsResponseDTO.SmsItem> allItems = smsResponse.getItems();

        // 找出发送失败的短信ID
        List<String> failedIds = allItems.stream()
                .filter(item -> !SUCCESS_CODE.equals(item.getCode()))
                .map(SmsResponseDTO.SmsItem::getCustomMsgID)
                .filter(StrUtil::isNotBlank)
                .collect(Collectors.toList());

        if (CollUtil.isEmpty(failedIds)) {
            log.info("所有短信发送成功！");
            return allItems;
        }

        log.info("发现{}条短信发送失败，尝试重新发送", failedIds.size());

        // 找出需要重发的短信内容
        List<SmsSendDTO.ItemInner> failedItems = originalList.stream()
                .filter(item -> failedIds.contains(item.getCustomMsgID()))
                .collect(Collectors.toList());

        if (CollUtil.isEmpty(failedItems)) {
            log.info("未找到对应的失败短信内容，直接返回原始结果");
            return allItems;
        }

        // 对失败的消息重新发送
        List<SmsResponseDTO.SmsItem> retryResults = sendSmSToUserWithRetry(failedItems, MAX_RETRY_COUNT);

        // 合并结果：用重试结果替换原有的失败结果
        return mergeSmsResults(allItems, retryResults, failedIds);
    }

    /**
     * 合并短信发送结果
     */
    private List<SmsResponseDTO.SmsItem> mergeSmsResults(
            List<SmsResponseDTO.SmsItem> originalResults,
            List<SmsResponseDTO.SmsItem> retryResults,
            List<String> originalFailedIds) {

        // 创建结果副本
        List<SmsResponseDTO.SmsItem> mergedResults = new ArrayList<>(originalResults);

        // 构建重试结果的映射，便于查找
        Map<String, SmsResponseDTO.SmsItem> retryResultMap = retryResults.stream()
                .collect(Collectors.toMap(
                        SmsResponseDTO.SmsItem::getCustomMsgID,
                        item -> item,
                        (existing, replacement) -> replacement
                ));

        // 用重试结果替换原有的失败结果
        for (int i = 0; i < mergedResults.size(); i++) {
            SmsResponseDTO.SmsItem originalItem = mergedResults.get(i);
            String msgId = originalItem.getCustomMsgID();

            if (originalFailedIds.contains(msgId)) {
                SmsResponseDTO.SmsItem retryItem = retryResultMap.get(msgId);
                if (retryItem != null) {
                    mergedResults.set(i, retryItem);
                }
                // 如果重试结果中没有找到对应的消息，保持原失败结果
            }
        }

        log.info("结果合并完成，原始结果数: {}, 重试结果数: {}, 合并后结果数: {}",
                originalResults.size(), retryResults.size(), mergedResults.size());

        return mergedResults;
    }

    /**
     * 构建失败响应
     */
    private List<SmsResponseDTO.SmsItem> buildFailedResponse(List<SmsSendDTO.ItemInner> itemList) {
        return itemList.stream()
                .map(item -> {
                    SmsResponseDTO.SmsItem failedItem = new SmsResponseDTO.SmsItem();
                    failedItem.setCustomMsgID(item.getCustomMsgID());
                    failedItem.setCode("-1");
                    failedItem.setMsg("短信发送失败，重试次数耗尽");
                    return failedItem;
                })
                .collect(Collectors.toList());
    }




   /* public List<SmsResponseDTO.SmsItem> sendSmSToUser(List<SmsSendDTO.ItemInner> temList,Boolean failFlag) {
        if (CollUtil.isEmpty(temList)) {
            log.error("短信发送列表为空");
            return Collections.emptyList();
        }

        SmsSendDTO smsSendDTO = new SmsSendDTO();
        smsSendDTO.setServiceCode("01001101");
        smsSendDTO.setAccount(account);

        String nowTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern(DatePattern.PURE_DATETIME_PATTERN));
        String sm3Hash = new SM3().digestHex(account + password + nowTime);
        smsSendDTO.setToken(sm3Hash);
        smsSendDTO.setTs(nowTime);
        smsSendDTO.setItems(temList);

        log.info("短信请求实体{}", smsSendDTO);

        String url = smsServer + "/sms/msg";
        System.out.println(url);
        try {
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            HttpEntity<String> requestEntity = new HttpEntity<>(new JSONObject(smsSendDTO).toString(), headers);

            ResponseEntity<SmsResponseDTO> response = restTemplate.exchange(
                    url,
                    HttpMethod.POST,
                    requestEntity,
                    SmsResponseDTO.class
            );
            // 处理响应
            return handleSmsResponse(response,failFlag,temList);
        } catch (Exception e) {
            log.error("短信接口调用失败", e);
            return new ArrayList<>();
        }
    }

    private List<SmsResponseDTO.SmsItem> handleSmsResponse(ResponseEntity<SmsResponseDTO> response,Boolean failFlag,List<SmsSendDTO.ItemInner> msgList) {
        if (response.getStatusCode() == HttpStatus.OK) {
            SmsResponseDTO smsResponse = response.getBody();
            List<SmsSendDTO.ItemInner> failList = new ArrayList<>();
            if (smsResponse != null && "0".equals(smsResponse.getCode())) {
                log.info("短信发送成功，batchId: {},发送条数{}", smsResponse.getBatchId(),smsResponse.getItems().size());
                List<String> ids = smsResponse.getItems().stream().filter(it->!"0".equals(it.getCode())).map(SmsResponseDTO.SmsItem::getCustomMsgID).collect(Collectors.toList());
                if(CollUtil.isNotEmpty(ids)){
                    //调用成功的情况下，依然会存在个别短信发送失败
                    List<SmsSendDTO.ItemInner> faliList = msgList.stream().filter(it->ids.contains(it.getCustomMsgID())).collect(Collectors.toList());
                    sendSmSToUser(faliList,false);
                }
                return smsResponse.getItems();
            } else {
                log.error("短信发送失败: {}", (smsResponse != null ? smsResponse.getMessage() : "API 返回异常"));
                //全部失败重新发送一次
                if(failFlag){
                    //失败重新发送
                    sendSmSToUser(msgList,false);
                }

                return new ArrayList<>();
            }
        } else {
            log.error("HTTP 请求失败，状态码: {}", response.getStatusCode());
            if(failFlag){
                //全部失败重新发送一次
                sendSmSToUser(msgList,false);
            }
            return new ArrayList<>();
        }
    }
*/


}
