package com.usky.alarm.service.impl;

import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.dyvmsapi.model.v20170525.SingleCallByTtsResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.profile.DefaultProfile;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.usky.alarm.domain.*;
import com.usky.alarm.mapper.BaseAlarmNoticeResultMapper;
import com.usky.alarm.mapper.SysUserMapper;
import com.usky.alarm.service.BaseAlarmNoticeResultService;
import com.usky.alarm.service.config.voice.VoiceNotice;
import com.usky.common.core.bean.CommonPage;
import com.usky.common.mybatis.core.AbstractCrudService;
import com.usky.system.domain.MceRequestVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import com.usky.system.RemoteMceService;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Collections;
import java.util.List;

/**
 * <p>
 * 告警通知结果 服务实现类
 * </p>
 *
 * @author han
 * @since 2023-09-25
 */
@Slf4j
@Service
public class BaseAlarmNoticeResultServiceImpl extends AbstractCrudService<BaseAlarmNoticeResultMapper, BaseAlarmNoticeResult> implements BaseAlarmNoticeResultService {
    @Autowired
    private VoiceNotice voiceNotice;
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private RemoteMceService remoteMceService;

    private static final String SMS_SIGN_NAME = "上海永天科技股份有限公司";
    private static final String SMS_TEMPLATE_CODE = "SMS_463791105";
    private static final String REGION_ID = "cn-beijing";
    private static final String ACCESS_KEY_ID = "LTAI5t7GgkVKSdAbPWAzUq8U";
    private static final String ACCESS_KEY_SECRET = "9zQ3e8GPTSlcfF1ev0JaBjlpvvSG6N";

    private static final String INFO_TYPE = "4";
    private static final String INFO_TITLE = "设备告警";
    private static final String ALARM_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
    private static final String REMARK_TEMPLATE = "设备名称：%s，请及时处理！";


    @Override
    public CommonPage<BaseAlarmNoticeResult> resultInfo(String receiver, Integer alarmId, Integer current, Integer size) {
        IPage<BaseAlarmNoticeResult> page = new Page<>(current, size);
        LambdaQueryWrapper<BaseAlarmNoticeResult> queryWrapper1 = Wrappers.lambdaQuery();
        queryWrapper1.like(StringUtils.isNotBlank(receiver), BaseAlarmNoticeResult::getReceiver, receiver)
                .eq(BaseAlarmNoticeResult::getAlarmId, alarmId);
//                .eq(BaseAlarmNoticeResult::getTenantId, SecurityUtils.getTenantId());
        page = this.page(page, queryWrapper1);
        return new CommonPage<>(page.getRecords(), page.getTotal(), page.getCurrent(), page.getSize());
    }

    // 异步多线程调用
    @Async("asyncServiceExecutor")
    public Integer send(BaseAlarm baseAlarm, List<BaseAlarmNotice> records3, Integer alarmId, List<DmpProduct> records,
                        BaseAlarmType baseAlarmType, List<DmpDevice> records2) throws ClientException {
        log.info("Start asyncServiceExecutor--------------------");
        Integer saveAlarmResult = 0;
        String templateParam = createTemplateParam(baseAlarm, baseAlarmType, records2.get(0));

        try {
            String[] receivers = records3.get(0).getReceiver1().split(",");
            for (String receiver : receivers) {
                SysUser sysUser = getSysUser(receiver);
                if (sysUser == null) {
                    log.warn("查询不到告警接收用户: {}", receiver);
                    continue;
                }

                BaseAlarmNoticeResult baseAlarmNoticeResult = createBaseAlarmNoticeResult(sysUser, baseAlarm, baseAlarmType, records.get(0), alarmId);

                if (records3.get(0).getNoticeMethod().contains("电话")) {
                    handleVoiceNotice(sysUser, baseAlarmNoticeResult, records.get(0), baseAlarmType, baseAlarm);
                    saveAlarmResult = baseMapper.insert(baseAlarmNoticeResult);
                }

                if (records3.get(0).getNoticeMethod().contains("短信")) {
                    handleSmsNotice(sysUser, baseAlarmNoticeResult, templateParam);
                    saveAlarmResult = baseMapper.insert(baseAlarmNoticeResult);
                }

                if (records3.get(0).getNoticeMethod().contains("APP")) {
                    handleMceNotice(sysUser, baseAlarmNoticeResult, baseAlarm, baseAlarmType, records2.get(0), "1");
                    saveAlarmResult = baseMapper.insert(baseAlarmNoticeResult);
                }

                if (records3.get(0).getNoticeMethod().contains("微信")) {
                    handleMceNotice(sysUser, baseAlarmNoticeResult, baseAlarm, baseAlarmType, records2.get(0), "2");
                    saveAlarmResult = baseMapper.insert(baseAlarmNoticeResult);
                }
            }
        } catch (Exception e) {
            log.error("发送报警通知时异常", e);
        }
        return saveAlarmResult;
    }

    private String createTemplateParam(BaseAlarm baseAlarm, BaseAlarmType baseAlarmType, DmpDevice device) {
        return "{\"deviceName\":\"" + device.getDeviceName() + "\"," +
                "\"time\":\"" + formatAlarmTime(baseAlarm.getAlarmTime()) + "\"," +
                "\"alarmType\":\"" + baseAlarmType.getTypeName() + "\"," +
                "\"alarmContent\":\"" + baseAlarm.getAlarmContent() + "\"}";
    }

    private SysUser getSysUser(String userId) {
        LambdaQueryWrapper<SysUser> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(SysUser::getUserId, userId)
                .eq(SysUser::getDelFlag, 0);
        return sysUserMapper.selectOne(queryWrapper);
    }

    private BaseAlarmNoticeResult createBaseAlarmNoticeResult(SysUser sysUser, BaseAlarm baseAlarm, BaseAlarmType baseAlarmType, DmpProduct product, Integer alarmId) {
        BaseAlarmNoticeResult result = new BaseAlarmNoticeResult();
        result.setReceiver(sysUser.getNickName());
        result.setReceiverPhone(sysUser.getPhonenumber());
        result.setAlarmId(alarmId);
        result.setNoticeTime(LocalDateTime.now());
        result.setNoticeContent(product.getProductName() + "," + baseAlarmType.getTypeName() + "," + formatAlarmTime(baseAlarm.getAlarmTime()));
        result.setTenantId(product.getTenantId());
        return result;
    }

    private void handleVoiceNotice(SysUser sysUser, BaseAlarmNoticeResult baseAlarmNoticeResult, DmpProduct product, BaseAlarmType baseAlarmType, BaseAlarm baseAlarm) {
        baseAlarmNoticeResult.setNoticeType(3);
        try {
            SingleCallByTtsResponse response = voiceNotice.sendCVoice(sysUser.getPhonenumber(),
                    product.getProductName(), baseAlarmType.getTypeName(),
                    formatAlarmTime(baseAlarm.getAlarmTime()));
            baseAlarmNoticeResult.setNoticeResult(response.getCode() != null && "OK".equals(response.getCode()) ? 1 : 2);
        } catch (Exception e) {
            log.error("用户：{}，告警消息电话拨打失败", sysUser.getUserId(), e);
            baseAlarmNoticeResult.setNoticeResult(2);
        }
    }

    private void handleSmsNotice(SysUser sysUser, BaseAlarmNoticeResult baseAlarmNoticeResult, String templateParam) {
        baseAlarmNoticeResult.setNoticeType(4);
        try {
            IAcsClient client = createAcsClient();
            SendSmsRequest request = new SendSmsRequest();
            request.setPhoneNumbers(sysUser.getPhonenumber());
            request.setSignName(SMS_SIGN_NAME);
            request.setTemplateCode(SMS_TEMPLATE_CODE);
            request.setTemplateParam(templateParam);
            SendSmsResponse response = client.getAcsResponse(request);
            baseAlarmNoticeResult.setNoticeResult(response.getCode() != null && "OK".equals(response.getCode()) ? 1 : 2);
        } catch (Exception e) {
            log.error("用户：{}，告警消息短信发送失败", sysUser.getUserId(), e);
            baseAlarmNoticeResult.setNoticeResult(2);
        }
    }

    private IAcsClient createAcsClient() {
        DefaultProfile profile = DefaultProfile.getProfile(REGION_ID, ACCESS_KEY_ID, ACCESS_KEY_SECRET);
        return new DefaultAcsClient(profile);
    }

    // 发送消息中心
    private void handleMceNotice(SysUser sysUser, BaseAlarmNoticeResult baseAlarmNoticeResult, BaseAlarm baseAlarm, BaseAlarmType baseAlarmType, DmpDevice device, String sendType) {
        MceRequestVO mceRequestVO = createMceRequestVO(sysUser, baseAlarm, baseAlarmType, device, sendType);

        try {
            remoteMceService.addMceReceive(mceRequestVO);
            baseAlarmNoticeResult.setNoticeResult(1);
        } catch (Exception e) {
            String noticeType = "1".equals(sendType) ? "APP" : "微信";
            log.error("用户：{}，告警消息{}推送失败:", sysUser.getUserId(), noticeType, e);
            baseAlarmNoticeResult.setNoticeResult(2);
        }

        // 设置通知类型
        baseAlarmNoticeResult.setNoticeType("1".equals(sendType) ? 1 : 2);
    }

    // 创建消息请求参数
    private MceRequestVO createMceRequestVO(SysUser sysUser, BaseAlarm baseAlarm, BaseAlarmType baseAlarmType, DmpDevice device, String sendType) {
        MceRequestVO mceRequestVO = new MceRequestVO();
        mceRequestVO.setInfoType(INFO_TYPE);
        mceRequestVO.setInfoTitle(INFO_TITLE);
        mceRequestVO.setDeviceId(device.getDeviceId());
        log.info("设备ID：{}", device.getDeviceId());
        mceRequestVO.setInfoContent(baseAlarmType.getTypeName());
        mceRequestVO.setAlarmTime(formatAlarmTime(baseAlarm.getAlarmTime()));
        log.info("告警时间：{}", baseAlarm.getAlarmTime());
        mceRequestVO.setAlarmSendType(sendType);
        mceRequestVO.setRemark(String.format(REMARK_TEMPLATE, device.getDeviceName()));
        mceRequestVO.setUserIds(Collections.singletonList(sysUser.getUserId()));
        mceRequestVO.setUserName(sysUser.getUserName());
        mceRequestVO.setId(baseAlarm.getId());
        mceRequestVO.setTenantId(baseAlarm.getTenantId());
        return mceRequestVO;
    }

    private String formatAlarmTime(LocalDateTime alarmTime) {
        return alarmTime.format(DateTimeFormatter.ofPattern(ALARM_TIME_FORMAT));
    }
}