package com.yc.ship.module.trade.service.smsSendconfig;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.yc.ship.framework.common.pojo.PageResult;
import com.yc.ship.framework.common.util.object.BeanUtils;
import com.yc.ship.framework.mybatis.core.util.MyBatisUtils;
import com.yc.ship.module.system.dal.dataobject.dict.DictDataDO;
import com.yc.ship.module.system.dal.dataobject.sms.SmsTemplateDO;
import com.yc.ship.module.system.dal.mysql.dict.DictDataMapper;
import com.yc.ship.module.system.dal.mysql.sms.SmsTemplateMapper;
import com.yc.ship.module.system.service.sms.SmsSendService;
import com.yc.ship.module.trade.api.sms.dto.SmsReqDTO;
import com.yc.ship.module.trade.controller.admin.smsSendconfig.vo.SmsSendconfigPageReqVO;
import com.yc.ship.module.trade.controller.admin.smsSendconfig.vo.SmsSendconfigQueryRespVO;
import com.yc.ship.module.trade.controller.admin.smsSendconfig.vo.SmsSendconfigSaveReqVO;
import com.yc.ship.module.trade.dal.dataobject.smsProduct.SmsProductDO;
import com.yc.ship.module.trade.dal.dataobject.smsSendLog.SmsSendLogDO;
import com.yc.ship.module.trade.dal.dataobject.smsSendconfig.SmsSendconfigDO;
import com.yc.ship.module.trade.dal.mysql.order.TradeOrderMapper;
import com.yc.ship.module.trade.dal.mysql.smsProduct.SmsProductMapper;
import com.yc.ship.module.trade.dal.mysql.smsSendLog.SmsSendLogMapper;
import com.yc.ship.module.trade.dal.mysql.smsSendconfig.SmsSendconfigMapper;
import com.yc.ship.module.trade.service.sms.SmsServiceImpl;
import com.yc.ship.module.trade.utils.SmsUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.lang3.StringUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

import static com.yc.ship.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.yc.ship.module.trade.enums.ErrorCodeConstants.SMS_SENDCONFIG_NOT_EXISTS;


/**
 * 短信发送配置 Service 实现类
 *
 * @author 管理员
 */
@Service
@Validated
@Slf4j
public class SmsSendconfigServiceImpl implements SmsSendconfigService {

    @Resource
    private SmsSendconfigMapper smsSendconfigMapper;

    @Resource
    private SmsProductMapper smsProductMapper;

    @Resource
    private SmsServiceImpl smsService;

    @Resource
    private SmsSendService smsSendService;

    @Resource
    private SmsSendLogMapper smsSendLogMapper;

    @Resource
    private TradeOrderMapper tradeOrderMapper;

    @Resource
    private SmsTemplateMapper smsTemplateMapper;
    @Resource
    private DictDataMapper dictDataMapper;

    @Override
    public Long createSmsSendconfig(SmsSendconfigSaveReqVO createReqVO) {
        // 插入
        SmsSendconfigDO smsSendconfig = BeanUtils.toBean(createReqVO, SmsSendconfigDO.class);
        smsSendconfig.setId(IdWorker.getId(smsSendconfig));
        smsSendconfigMapper.insert(smsSendconfig);

//        smsProductMapper.delete(SmsProductDO::getSmsTemplateId, smsSendconfig.getId());
        List<SmsProductDO> smsProductList = new ArrayList<>();
        for (Long productId : createReqVO.getProductIdList()) {
            SmsProductDO smsProductDO = new SmsProductDO();
            smsProductDO.setId(IdWorker.getId(smsProductDO));
            smsProductDO.setProductId(productId);
            smsProductDO.setSmsTemplateId(smsSendconfig.getId());
            smsProductList.add(smsProductDO);
        }
        smsProductMapper.insertBatch(smsProductList);
        if (createReqVO.getSendType() != null && createReqVO.getSendType() == 1) {
            smsSendMsg(1, smsSendconfig.getId());
        }
        return smsSendconfig.getId();
    }

    @Override
    public void updateSmsSendconfig(SmsSendconfigSaveReqVO updateReqVO) {
        // 校验存在
        validateSmsSendconfigExists(updateReqVO.getId());
        // 更新
        SmsSendconfigDO updateObj = BeanUtils.toBean(updateReqVO, SmsSendconfigDO.class);
        smsSendconfigMapper.updateById(updateObj);

        smsProductMapper.delete(SmsProductDO::getSmsTemplateId, updateReqVO.getId());
        List<SmsProductDO> smsProductList = new ArrayList<>();
        for (Long productId : updateReqVO.getProductIdList()) {
            SmsProductDO smsProductDO = new SmsProductDO();
            smsProductDO.setId(IdWorker.getId(smsProductDO));
            smsProductDO.setProductId(productId);
            smsProductDO.setSmsTemplateId(updateObj.getId());
            smsProductList.add(smsProductDO);
        }
        smsProductMapper.insertBatch(smsProductList);

    }

    @Override
    public void deleteSmsSendconfig(Long id) {
        // 校验存在
        validateSmsSendconfigExists(id);
        // 删除
        smsSendconfigMapper.deleteById(id);

        smsProductMapper.delete(SmsProductDO::getSmsTemplateId, id);
    }

    private void validateSmsSendconfigExists(Long id) {
        if (smsSendconfigMapper.selectById(id) == null) {
            throw exception(SMS_SENDCONFIG_NOT_EXISTS);
        }
    }

    @Override
    public SmsSendconfigDO getSmsSendconfig(Long id) {
        SmsSendconfigDO smsSendconfigDO = smsSendconfigMapper.selectById(id);
        List<SmsProductDO> list = smsProductMapper.selectList(SmsProductDO::getSmsTemplateId, smsSendconfigDO.getId());
        List<Long> productIds = list.stream().map(SmsProductDO::getProductId).distinct().collect(Collectors.toList());
        smsSendconfigDO.setProductIdList(productIds);
        return smsSendconfigDO;
    }

    @Override
    @Async
    public void smsSendMsg(int type, Long id) {
        //发送短信
        List<SmsSendconfigQueryRespVO> list = smsSendconfigMapper.querySendList(id, type);
        for (SmsSendconfigQueryRespVO smsSendconfigQueryRespVO : list) {
            SmsReqDTO smsReqDTO = new SmsReqDTO();
            if (type == 0) {
                Integer sendType = smsSendconfigQueryRespVO.getSendType();
                try {
                    if (sendType != null && sendType == 2) {
                        //sendTime 17:30
                        String sendTime = smsSendconfigQueryRespVO.getSendTime();
                        // 1.出行当天 2.出行前1天 3.出行前2天 4.出行前3天 5.出行前4天 6.出行前5天 7.出行前6天 8.出行前7天
                        Integer sendDateType = smsSendconfigQueryRespVO.getSendDateType();
                        if (sendDateType != null && sendDateType == 1) {
                            //2025-01-22 19:00
                            String dateStr = smsSendconfigQueryRespVO.getUseDate().substring(0, 10) + " " + sendTime;
                            //2025-01-22 17:30
                            Date sendTimeDate = DateUtil.parse(dateStr, DatePattern.NORM_DATETIME_MINUTE_PATTERN);
                            //当前时间大于发送时间，则跳过
                            if (DateUtil.isSameDay(sendTimeDate, new Date()) || DateUtil.tomorrow().compareTo(sendTimeDate) < 0) {
                                continue;
                            }
                        }
                        if (sendDateType != null && sendDateType == 2) {
                            String dateStr = smsSendconfigQueryRespVO.getUseDate().substring(0, 10) + " " + sendTime;
                            Date sendTimeDate = DateUtil.parse(dateStr, DatePattern.NORM_DATETIME_MINUTE_PATTERN);
                            //当前时间小于发送时间，则跳过
                            //2025-01-01 17:30
                            if (new Date().compareTo(sendTimeDate) < 0) {
                                continue;
                            }
                        }
                    } else {
                        continue;
                    }
                } catch (Exception e) {
                    log.error("定时任务发送短信异常,解析失败", e);
                    break;
                }
            }
            //sxly
            String appId = smsSendconfigQueryRespVO.getApiKey();
            //Sx@202305
            String secretKey = smsSendconfigQueryRespVO.getApiSecret();
            //https://112.35.10.201:58888/sms/tmpsubmit
            String url = smsSendconfigQueryRespVO.getApiUrl();
            //jFKNw6Cis
            String signName = smsSendconfigQueryRespVO.getSignature();

            SmsSendLogDO smsSendLogDO = new SmsSendLogDO();
            smsSendLogDO.setId(IdWorker.getId(smsSendLogDO));
            smsSendLogDO.setMobile(smsSendconfigQueryRespVO.getMobile());
            smsSendLogDO.setOrderNo(smsSendconfigQueryRespVO.getOrderNo());
            smsSendLogDO.setSmsConfigId(smsSendconfigQueryRespVO.getId() + "");

            List<String> mobileList = new ArrayList<>();
            mobileList.add(smsSendconfigQueryRespVO.getMobile());
            smsReqDTO.setMobile(mobileList);
            smsReqDTO.setSmsTemplateId(smsSendconfigQueryRespVO.getApiTemplateId());
            String content = smsSendconfigQueryRespVO.getSmsParms();

            //【1】航次名称； 【2】订单号； 【3】游玩日期； 【4】联系人；【5】购买数量；
            //            【6】团号； 【7】旅行社联系人； 【8】联系电话；【9】航线名称；【10】产品简称；【11】咨询电话；【12】游船；【13】开航时间；
            //            【14】出发时间；【15】违约金；【16】补缴费；【17】小程序链接；【18】登船时间
            content = content.replaceAll("【1】", smsSendconfigQueryRespVO.getVoyageName());
            content = content.replaceAll("【2】", smsSendconfigQueryRespVO.getOrderNo());
            content = content.replaceAll("【3】", smsSendconfigQueryRespVO.getUseDate().substring(0, 10));
            content = content.replaceAll("【12】", smsSendconfigQueryRespVO.getShipName());
            content = content.replaceAll("【13】", smsSendconfigQueryRespVO.getUseDate().substring(0, 10));
            content = content.replaceAll("【4】", smsSendconfigQueryRespVO.getContactName());
            content = content.replaceAll("【5】", smsSendconfigQueryRespVO.getNum() + "");
            content = content.replaceAll("【6】", smsSendconfigQueryRespVO.getGroupNo());
            content = content.replaceAll("【7】", smsSendconfigQueryRespVO.getContactName());
            content = content.replaceAll("【8】", smsSendconfigQueryRespVO.getMobile());
            content = content.replaceAll("【9】", smsSendconfigQueryRespVO.getRouteName());
            content = content.replaceAll("【10】", smsSendconfigQueryRespVO.getShortName());
            content = content.replaceAll("【14】", smsSendconfigQueryRespVO.getLeaveTime().substring(0, 10));
            content = content.replaceAll("【18】", smsSendconfigQueryRespVO.getLeaveTime().substring(0, 10));
            DateTime dateTime = DateUtil.offsetDay(DateUtil.parse(smsSendconfigQueryRespVO.getLeaveTime()), -7);
            DateTime dateTime2 = DateUtil.offsetDay(DateUtil.parse(smsSendconfigQueryRespVO.getLeaveTime()), -1);
            content = content.replaceAll("【19】", DateUtil.format(dateTime, "yyyy-MM-dd"));
            content = content.replaceAll("【20】", DateUtil.format(dateTime2, "yyyy-MM-dd"));

            smsReqDTO.setSmsContent(content);
            String result;
            if (StringUtils.isNotBlank(smsSendconfigQueryRespVO.getChannelCode()) && StringUtils.equals("UNICOM", smsSendconfigQueryRespVO.getChannelCode())) {
                JSONArray parts = JSONUtil.parseArray(content);
                JSONArray templates = JSONUtil.parseArray(smsSendconfigQueryRespVO.getTemplateParams());
                Map<Object, Object> map = new HashMap<>();
                for (int i = 0; i < templates.size(); i++) {
                    String key = templates.getStr(i);
                    String value = parts.getStr(i);
                    map.put(key, value);
                }
                String content2 = StrUtil.format(smsSendconfigQueryRespVO.getSmsContent(), map);
                smsSendLogDO.setSmsContent(content2);
                String mobile = smsSendconfigQueryRespVO.getMobile();
                log.error("[下单成功短信发送参数]：{};手机号：{}", content2, mobile);
                HttpClient httpclient = new HttpClient();
                PostMethod post = new PostMethod(url);
                post.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, "gbk");
                post.addParameter("SpCode", signName);
                post.addParameter("LoginName", appId);
                post.addParameter("Password", secretKey);
                post.addParameter("MessageContent", content);
                post.addParameter("UserNumber", mobile);
                Random random = new Random();
                int ranNum = random.nextInt(9);
                String serialNumber = SmsUtil.createOrderNo(ranNum + "");
                if (serialNumber.length() > 20) {
                    serialNumber = serialNumber.substring(0, 19);
                }
                post.addParameter("SerialNumber", serialNumber);
                post.addParameter("ScheduleTime", "");
                post.addParameter("templateId", smsSendconfigQueryRespVO.getApiTemplateId());
                post.addParameter("f", "1");
                try {
                    httpclient.executeMethod(post);
                    result = new String(post.getResponseBody(), "gbk");
                    log.error("[下单成功短信返回参数]：{}", result);
                } catch (Exception e) {
                    log.error("[下单成功短信发送异常]：{}", e.getMessage());
                    result = "发送失败" + e.getMessage();
                }
            } else {
                smsSendLogDO.setSmsContent(content);
                result = smsService.sendMsg(smsReqDTO);
            }
            smsSendLogDO.setResult(result);
            if (result != null && result.contains("成功")) {
                smsSendLogDO.setStatus(1);
            } else {
                smsSendLogDO.setStatus(0);
            }
            smsSendLogMapper.insert(smsSendLogDO);

        }
    }


    @Override
    public PageResult<SmsSendconfigDO> getSmsSendconfigPage(SmsSendconfigPageReqVO pageReqVO) {
        return smsSendconfigMapper.selectPage(pageReqVO);
    }

    @Override
    public PageResult<SmsSendconfigQueryRespVO> querySendLogList(SmsSendconfigPageReqVO pageReqVO) {
        IPage<SmsSendconfigDO> iPage = MyBatisUtils.buildPage(pageReqVO);
        IPage<SmsSendconfigQueryRespVO> page = smsSendconfigMapper.querySendLogList(iPage, pageReqVO);
        return new PageResult<>(page.getRecords(), page.getTotal());
    }

    /**
     * @param type 1 上水 2 下水
     * @param code
     * @param day 天数
     */
    @Override
    @Async
    public void upSmsSendMsg(int type, String code, int day) {
        // 查询订单联系人
        List<Map<String,Object>> linkList = tradeOrderMapper.queryOrderLink(day,type);
        // 查询接站登记人
        List<Map<String,Object>> jzPhoneList = tradeOrderMapper.queryOrderJzPhone(day,type);
        // 查询订单游客电话
        List<Map<String,Object>> visitorMobileList = tradeOrderMapper.queryOrderVisitorMobile(day,type);
        // 查询短信配置
        SmsTemplateDO smsTemplateDO = smsTemplateMapper.selectByCode(code);
        // 合并两个列表并去重
        Set<String> phoneSet = new HashSet<>();
        Map<String, Map<String, Object>> phoneDataMap = new HashMap<>();
        processPhoneList(linkList, "link_mobile", phoneSet, phoneDataMap);
        processPhoneList(jzPhoneList, "phone", phoneSet, phoneDataMap);
        processPhoneList(visitorMobileList, "mobile", phoneSet, phoneDataMap);

        List<String> phoneList = new ArrayList<>(phoneSet);
        List<String> params = smsTemplateDO.getParams();// ["【pick】","【time】"]
        Map<String, Object> templateParams = new HashMap<>();
        if(type == 1){
            // 上水
            // 获取上水抵达三峡游客中心 查询数据字典
            List<DictDataDO> arriveDataLis = dictDataMapper.selectListByStatusAndDictType(0, "up_arrive");
            if(day == 1){
                // 获取上水登船时间 查询数据字典
                List<DictDataDO> dictDataList = dictDataMapper.selectListByStatusAndDictType(0, "up_board");
                templateParams.put(params.get(0), dictDataList.get(0).getLabel());
                templateParams.put(params.get(1), arriveDataLis.get(0).getLabel());
            }else{
                templateParams.put(params.get(0), DateUtil.format(DateUtil.offsetDay(new Date(), day), "yyyy年MM月dd日"));
                templateParams.put(params.get(1), arriveDataLis.get(0).getLabel());
            }
        }else{
            // 下水
            if(day == 1){
                // 获取下水登船时间 查询数据字典
                List<DictDataDO> dictDataList = dictDataMapper.selectListByStatusAndDictType(0, "down_board");
                templateParams.put(params.get(0), dictDataList.get(0).getLabel());
            }else{
                templateParams.put(params.get(0), DateUtil.format(DateUtil.offsetDay(new Date(), day), "yyyy年MM月dd日"));
            }
        }
        if(CollectionUtil.isNotEmpty(phoneList)){
            for(String phone : phoneList){
//                log.info("【短信发送】：phone:{}", phone);
//                log.info("【短信发送】：templateParams:{}", templateParams);
                smsSendService.sendSingleSmsToAdmin(phone, null, smsTemplateDO.getId(), templateParams);
            }
//            smsSendService.sendSingleSmsToAdmin("18071246889", null, smsTemplateDO.getId(), templateParams);
        }
    }

    private void processPhoneList(List<Map<String, Object>> dataList, String phoneKey,
                                  Set<String> phoneSet, Map<String, Map<String, Object>> phoneDataMap) {
        if (dataList == null) {
            return;
        }
        for (Map<String, Object> map : dataList) {
            String phone = (String) map.get(phoneKey);
            if (phone != null && !phone.isEmpty()) {
                phoneSet.add(phone);
                if (!phoneDataMap.containsKey(phone)) {
                    phoneDataMap.put(phone, map);
                }
            }
        }
    }

}