package com.zksy.api.utils;

import com.alibaba.fastjson.JSONObject;
import com.aliyun.auth.credentials.Credential;
import com.aliyun.auth.credentials.provider.StaticCredentialProvider;
import com.aliyun.sdk.service.dysmsapi20170525.AsyncClient;
import com.aliyun.sdk.service.dysmsapi20170525.models.SendBatchSmsRequest;
import com.aliyun.sdk.service.dysmsapi20170525.models.SendBatchSmsResponse;
import com.google.gson.Gson;
import com.zksy.api.config.AliyunSmsConfig;
import com.zksy.api.domain.Enum.DeviceCodeEnum;
import com.zksy.api.domain.Enum.WarningCodeEnum;
import com.zksy.api.domain.WarningThreshold;
import com.zksy.api.service.WarningThresholdService;
import darabonba.core.client.ClientOverrideConfiguration;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import rk.netDevice.sdk.p2.NodeData;
import rk.netDevice.sdk.p2.RealTimeData;

import java.time.Duration;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

@Component
@Slf4j
public class SmsUtil {

    private final AliyunSmsConfig aliyunSmsConfig;
    private final AsyncClient client;

    private final WarningThresholdService service;

    // 报警缓存和冷却时间
//    private static final Map<String, Long> ALARM_CACHE = new ConcurrentHashMap<>();
//    private static final long ALARM_COOLDOWN_MS = 5 * 60 * 1000;

    @Autowired
    public SmsUtil(AliyunSmsConfig aliyunSmsConfig, WarningThresholdService service) {
        this.aliyunSmsConfig = aliyunSmsConfig;
        this.service=service;

        try {
            StaticCredentialProvider provider = StaticCredentialProvider.create(Credential.builder()
                    .accessKeyId(aliyunSmsConfig.getAccessKeyId())
                    .accessKeySecret(aliyunSmsConfig.getAccessKeySecret())
                    .build());

            this.client = AsyncClient.builder()
                    .region(aliyunSmsConfig.getRegionId())
                    .credentialsProvider(provider)
                    .overrideConfiguration(
                            ClientOverrideConfiguration.create()
                                    .setEndpointOverride("dysmsapi.aliyuncs.com")
                                    .setConnectTimeout(Duration.ofSeconds(30))
                    )
                    .build();
        } catch (Exception e) {
            log.error("阿里云短信客户端初始化失败", e);
            throw new RuntimeException("短信服务初始化异常", e); // 初始化失败应快速失败
        }
    }
    /**
     * 批量发送相同内容的短信给多个手机号
     * @param phoneNumbers 接收短信的手机号列表
     * @param templateParam 短信模板参数，JSON格式字符串
     * @return 发送结果，key为手机号，value为是否成功
     */
    public Map<String, Boolean> sendBatchSms(List<String> phoneNumbers, String templateParam) {
        if (phoneNumbers == null || phoneNumbers.isEmpty()) {
            log.warn("批量发送短信失败：手机号列表为空");
            return Collections.emptyMap();
        }

        try {
            List<String> signNames = phoneNumbers.stream()
                    .map(phone -> aliyunSmsConfig.getSignName())
                    .collect(Collectors.toList());

            List<String> templateParams = phoneNumbers.stream()
                    .map(phone -> templateParam)
                    .collect(Collectors.toList());

            //构建批量发送请求
            SendBatchSmsRequest request = SendBatchSmsRequest.builder()
                    .phoneNumberJson(new Gson().toJson(phoneNumbers)) // 手机号列表
                    .signNameJson(new Gson().toJson(signNames)) // 签名列表
                    .templateCode(aliyunSmsConfig.getTemplateCode())
                    .templateParamJson(new Gson().toJson(templateParams)) // 参数列表
                    .build();

            // 发送并处理响应
            CompletableFuture<SendBatchSmsResponse> response = client.sendBatchSms(request);
            SendBatchSmsResponse resp = response.get();

            log.info("批量短信发送响应: {}",new Gson().toJson(resp.getBody()));
            return phoneNumbers.stream()
                    .collect(Collectors.toMap(
                            phone -> phone,
                            phone -> "OK".equals(resp.getBody().getCode())
                    ));
        } catch (Exception e) {
            log.error("批量短信发送响应: {}",e.getMessage());
            e.printStackTrace();
            return phoneNumbers.stream()
                    .collect(Collectors.toMap(
                            phone -> phone,
                            phone -> false
                    ));
        }
    }
    /**
     * 检查设备数据是否触发报警并发送短信
     */
    public boolean checkDeviceAlarmAndSend(RealTimeData realTimeData, NodeData nodeData, List<String> alarmPhones) {

        if (realTimeData == null || nodeData == null) {
            log.error("预警参数异常：设备数据或节点数据为空");
            return false;
        }
        if (realTimeData.getDeviceId() <= 0) {
            log.error("预警参数异常：设备ID无效（{}）", realTimeData.getDeviceId());
            return false;
        }

        int nodeId = nodeData.getNodeId();
        if (nodeId < 1 || nodeId > 5) {
            log.error("节点ID无效（{}），仅支持1-5的节点", nodeId);
            return false;
        }

        try {

            //TODO 冷处理待定
//            String cacheKey = realTimeData.getDeviceId() + "_" + nodeId;
//            Long lastAlarmTime = ALARM_CACHE.get(cacheKey);
//            if (lastAlarmTime != null && System.currentTimeMillis() - lastAlarmTime < ALARM_COOLDOWN_MS) {
//                log.info("设备{}节点{}在冷却时间内，暂不重复报警", realTimeData.getDeviceId(), nodeId);
//                return false;
//            }

            // 根据node_id匹配唯一预警类型
            WarningCodeEnum targetWarningType = getWarningTypeByNodeId(nodeId);
            if (targetWarningType == null) {
                log.warn("设备{}节点{}无对应预警类型，跳过检查", realTimeData.getDeviceId(), nodeId);
                return false;
            }
            String warningCode = targetWarningType.getCode();
            String warningMsg = targetWarningType.getName();

            // 直接查询该预警类型的阈值
            double actualThreshold;
            try {
                String deviceCode = DeviceCodeEnum.ENVIRONMENT_DEVICE.getCode();
                WarningThreshold threshold = service.getWarningThresholdByDeviceAndCode(deviceCode, warningCode);

                // 优先使用数据库配置，无配置则用枚举默认值
                actualThreshold = (threshold != null && threshold.getWarningValue() != null)
                        ? threshold.getWarningValue()
                        : targetWarningType.getDefaultVal();
            } catch (Exception e) {
                log.error("查询预警阈值失败，使用默认值", e);
                actualThreshold = targetWarningType.getDefaultVal();
            }

            // 获取当前节点的指标数值
            double currentValue = getCurrentValueByNodeId(nodeData, nodeId);

            boolean isOverThreshold = currentValue > actualThreshold;

            log.debug("设备{}节点{} - 预警类型：{}，当前值：{}，阈值：{}，是否超限：{}",
                    realTimeData.getDeviceId(), nodeId, warningMsg, currentValue, actualThreshold, isOverThreshold);

            // 超过期限，触发报警
            if (isOverThreshold) {
                log.warn("设备{}节点{}触发预警：{}（当前值：{} > 阈值：{}）",
                        realTimeData.getDeviceId(), nodeId, warningMsg, currentValue, actualThreshold);

                // 构造短信参数
                JSONObject params = new JSONObject();
                params.put("deviceNo", realTimeData.getDeviceId());
                params.put("alarmType", warningMsg);
                // 经纬度处理（为执行信息处理）
                double lng = nodeData.getLng();
                double lat = nodeData.getLat();
                params.put("location", String.format("经纬度：%.6f,%.8f", lng, lat));

                Map<String, Boolean> sendResults = this.sendBatchSms(alarmPhones, params.toJSONString());
                long successCount = sendResults.values().stream().filter(Boolean::booleanValue).count();
                log.info("设备{}报警短信发送完成，成功{}条，失败{}条",
                        realTimeData.getDeviceId(), successCount, sendResults.size() - successCount);

                // 冷却处理
                // ALARM_CACHE.put(cacheKey, System.currentTimeMillis());
                return true;
            }
            return false;
        } catch (Exception e) {
            log.error("设备{}节点{}报警处理失败", realTimeData.getDeviceId(), nodeId, e);
            return false;
        }
    }

    /**
     * 根据nodeId获取对应的预警类型
     */
    private WarningCodeEnum getWarningTypeByNodeId(int nodeId) {
        switch (nodeId) {
            case 1: return WarningCodeEnum.SUSPENDED_SOLIDS;
            case 2: return WarningCodeEnum.COD;
            case 3: return WarningCodeEnum.AMMONIA_NITROGEN;
            case 4: return WarningCodeEnum.CONDUCTIVITY;
            case 5: return WarningCodeEnum.PH;
            default: return null;
        }
    }

    /**
     * 根据nodeId获取对应的指标数值
     */
    private double getCurrentValueByNodeId(NodeData nodeData, int nodeId) {
        if (nodeId == 1) {
            // 节点1需要特殊处理，取悬浮物字段（floatValue字段）
            return nodeData.getFloatValue();
        } else {
            // 其他节点取hum字段
            return nodeData.getHum();
        }
    }
}
