package com.clx.performance.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.clx.performance.common.MqWrapper;
import com.clx.performance.config.ConfiguredOpenProperties;
import com.clx.performance.enums.InternalMessageTemplateEnum;
import com.clx.performance.param.mq.InternalMessageParam;
import com.clx.performance.service.SendInternalMessageService;
import com.msl.common.base.PageData;
import com.msl.common.open.ConfiguredOpenClient;
import com.msl.common.result.Result;
import com.msl.message.in.app.api.content.DefaultMessageContent;
import com.msl.message.in.app.api.message.InAppDefaultMessage;
import com.msl.message.in.app.api.recipient.SpecifiesRecipient;
import com.msl.message.in.app.api.route.DefaultMessageRoute;
import com.msl.message.sdk.action.MessageAction;
import com.msl.user.feign.UserFeign;
import com.msl.user.param.user.external.PageProductUsersParam;
import com.msl.user.vo.user.external.PageProductUserVo;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import static com.clx.performance.constant.RabbitKeyConstants.SEND_CARRIER_INTERNAL_MESSAGE_EXCHANGE;
import static com.clx.performance.constant.RabbitKeyConstants.SEND_CARRIER_INTERNAL_MESSAGE_ROUTING_KEY;

/**
 * @ClassName SendInternalMessageServiceImpl
 * @Description
 * @Author kavin
 * @Date 2024/10/16 13:37
 * @Version 1.0
 */

@Slf4j
@Service
@AllArgsConstructor
public class SendInternalMessageServiceImpl implements SendInternalMessageService {


    private final ConfiguredOpenClient configuredOpenClient;
    private final ConfiguredOpenProperties configuredOpenProperties;
    private final UserFeign userFeign;
    private final RabbitTemplate rabbitTemplate;




    //发送站内信的业务Code

    @Override
    public void sendInternalMessageMq(String productCode,String businessType, Integer typeCode, List<Object> variableList, List<Object> jumpUrlVariableList,Long userNo){
        InternalMessageParam param = new InternalMessageParam();
        param.setBusinessType(businessType);
        param.setTypeCode(typeCode);
        param.setVariableList(variableList);
        param.setJumpUrlVariableList(jumpUrlVariableList);
        param.setUserNo(userNo);
        param.setProductCode(productCode);
        log.info("发送站内信消息开始,站内信业务类型{}，实际业务Code：{},消息内容:{}", businessType,typeCode,JSON.toJSONString(param));
        Message body = MessageBuilder.withBody(JSON.toJSONString(new MqWrapper<>(param)).getBytes()).build();
        rabbitTemplate.send(SEND_CARRIER_INTERNAL_MESSAGE_EXCHANGE,
                SEND_CARRIER_INTERNAL_MESSAGE_ROUTING_KEY, body);
        log.info("发送站内信消息结束,站内信业务类型{}，实际业务Code：{},", businessType,typeCode);
    }



    //查找字符在字符串出现的次数
    public static int countCharTimes(String mainStr,String subStr){
        // 声明一个要返回的变量
        int count = 0;
        // 声明一个初始的下标，从初始位置开始查找
        int index = 0;
        // 获取主数据的长度
        int mainStrLength = mainStr.length();
        // 获取要查找的数据长度
        int subStrLength = subStr.length();
        // 如果要查找的数据长度大于主数据的长度则返回0
        if (subStrLength > mainStrLength){
            return 0;
        }
        // 循环使用indexOf查找出现的下标，如果出现一次则count++

        while ((index = mainStr.indexOf(subStr, index)) != -1) {
            count++;
            index += subStrLength;
        }
        return count;
    }




    /**
     * 发送消息JSON实例：{"type": "in_app_default_message", "route": {"$ref": "$.messageRoute"}, "content": {"data": {"page": "message_operation_code:coal_source_publish_success_sales", "tonnage": "700.00", "coalType": "喜喜煤", "demandId": 932, "publisher": "陈小云", "unitPrice": "123.85", "demandType": "销售需求", "companyName": "产权交易中心", "jumpPageUrls": {"trade-operation-pc": "/demand/sale-detail/932"}, "inAppSendType": 2, "calorificValue": 7700, "validityPeriod": "2024-07-23 15:11:00-2024-07-23 23:11:00", "extraShowInfoList": [{"code": "companyName", "name": "企业名称", "unit": "", "value": "产权交易中心"}, {"code": "publisher", "name": "发布人姓名", "unit": "", "value": "陈小云"}, {"code": "coalType", "name": "煤种", "unit": "", "value": "喜喜煤"}, {"code": "calorificValue", "name": "热值", "unit": "kcal", "value": 7700}, {"code": "unitPrice", "name": "单价", "unit": "元/吨", "value": "123.85"}, {"code": "tonnage", "name": "吨数", "unit": "吨", "value": "700.00"}, {"code": "validityPeriod", "name": "有效期", "unit": "", "value": "2024-07-23 15:11:00-2024-07-23 23:11:00"}], "inAppSendTypeName": "全局提示"}, "type": "template_content", "templateKey": "SMB-INAPP-00001"}, "showType": "2", "accessKey": "CLX-OPERATION", "recipient": {"$ref": "$.messageRecipient"}, "channelKey": "in_app", "messageSign": "1", "messageGroup": "4", "messageRoute": {"type": "default_route", "routeMap": {"trade-operation-pc": ["default"]}}, "messageContent": {"$ref": "$.content"}, "messageSignName": "需求上报", "messageGroupName": "需求信息", "messageRecipient": {"type": "specifies_recipient", "users": [1021110826118750277, 1021252468523831365, 1021138417641676869, 1021095992956997701, 1021081090547744837]}, "validityLimitTime": "2024-07-24 15:12:04"}
     * socket推送JSON实例：{"productCode":"trade-client-app","functionKey":"CLX-SMB-SALES","userKey":"1021138417641676869","deliverToCompany":1,"companyKey":"1121232210178818117","userTag":null,"message":{"bizType":"in_app","body":{"id":16674,"messageNo":"1292033698861125","accessKey":"CLX-SMB-SALES","companyNo":"1121232210178818117","userNo":"1021138417641676869","messageGroup":"2","messageSign":"4","messageGroupName":"交易提醒","messageSignName":"交易提醒","showType":"3","showPriority":null,"validityLimitTime":"2024-07-25 15:12:04","showStatus":null,"showTime":null,"receivePage":null,"jumpPage":null,"markdownFlag":null,"status":null,"statusName":null,"readTime":null,"executedTime":null,"textVo":{"title":"需求发布成功","subtitle":"您好，当前企业有销售需求发布成功，请及时关注；【喜喜煤】/【7700kcal】/【700.00吨】/【123.85元/吨】，发布人：【陈小云】","content":null,"dataJson":"{\"unitPrice\":\"123.85\",\"calorificValue\":7700,\"demandId\":932,\"inAppSendType\":3,\"inAppSendTypeName\":\"消息通知\",\"jumpPageAppParam\":{\"id\":\"932\",\"underFlag\":\"1\"},\"coalType\":\"喜喜煤\",\"publisher\":\"陈小云\",\"jumpPageAppUrl\":\"/ReleaseDetailsPage\",\"tonnage\":\"700.00\",\"page\":\"message_code:demand_publish_success_sales\",\"extraShowInfoList\":[{\"unit\":\"\",\"code\":\"coalType\",\"name\":\"煤种\",\"value\":\"喜喜煤\"},{\"unit\":\"kcal\",\"code\":\"calorificValue\",\"name\":\"热值\",\"value\":7700},{\"unit\":\"吨\",\"code\":\"tonnage\",\"name\":\"吨数\",\"value\":\"700.00\"},{\"unit\":\"元/吨\",\"code\":\"unitPrice\",\"name\":\"单价\",\"value\":\"123.85\"},{\"unit\":\"\",\"code\":\"publisher\",\"name\":\"发布人姓名\",\"value\":\"陈小云\"}]}"},"createTime":null},"bodyType":3}}
     */

    //发送承运站内信
    @Override
    public void sendCarrierInternalMessage(InternalMessageParam internalMessageDTO) {

        Map<Integer, String> businessRelationMap = InternalMessageTemplateEnum.businessTypeMap.get(
                internalMessageDTO.getBusinessType());

        if(MapUtils.isEmpty(businessRelationMap)){
            log.warn("通过业务类型：{}, 在businessTypeMap 未找到对应的映射关系",internalMessageDTO.getBusinessType());
            return;
        }

        String businessTypeDetailCode = businessRelationMap.get(internalMessageDTO.getTypeCode());

        if(StringUtils.isBlank(businessTypeDetailCode)){
            log.warn("通过详细业务类型：{}, businessRelationMap 未找到对应的站内信详细业务类型关系",internalMessageDTO.getTypeCode());
            return;
        }

        Optional<InternalMessageTemplateEnum.TemplateType> templateTypeOptional = InternalMessageTemplateEnum.TemplateType.getByBusinessTypeDetailCode(
                businessTypeDetailCode);

        if(templateTypeOptional.isEmpty()){
            log.error("通过站内信业务详情Code未找到对应的枚举类型，code:{}",businessTypeDetailCode);
            return;
        }
        InternalMessageTemplateEnum.TemplateType templateType = templateTypeOptional.get();

        InAppDefaultMessage message = new InAppDefaultMessage();
        //消息
        message.setMessageGroup(templateType.getMessageType().getCode());
        message.setMessageGroupName(templateType.getMessageType().getName());
        message.setMessageSign(templateType.getBusinessType().getCode());
        message.setMessageSignName(templateType.getBusinessType().getName());

        message.setAccessKey(configuredOpenProperties.getCarrierInternalMessageAccessKey());

        //发送站内信
        DefaultMessageRoute messageRoute = new DefaultMessageRoute();
        // 自己定义，提供给消息中心
        messageRoute.put("product-code",internalMessageDTO.getProductCode());
        message.setMessageRoute(messageRoute);


        //直接指定内容
        DefaultMessageContent defaultMessageContent = new DefaultMessageContent();
        defaultMessageContent.setTitle(templateType.getBusinessDetailType().getTitle());
        defaultMessageContent.setContext(replaceContent(templateType.getBusinessDetailType().getContent(),internalMessageDTO.getVariableList()));

        HashMap<String,Object> data = new HashMap<>();
        data.put("businessDetailTypeCode",templateType.getBusinessDetailType().getCode());
        data.put("businessDetailTypeTitle",templateType.getBusinessDetailType().getTitle());
        if(StringUtils.isNotBlank(templateType.getBusinessDetailType().getJumpUrl())){
            data.put("jumpUrl",templateType.getBusinessDetailType().getJumpUrl());

        }
        if(StringUtils.isNotBlank(templateType.getBusinessDetailType().getParamJson())){
            String jumpUrlParamJson = replaceContent(templateType.getBusinessDetailType().getParamJson(),
                    internalMessageDTO.getJumpUrlVariableList());
            data.putAll(JSON.parseObject(jumpUrlParamJson,new TypeReference<Map<String, String>>(){}));
        }
        defaultMessageContent.setData(data);


        message.setMessageContent(defaultMessageContent);


        //组装发送人 指定接收人
        SpecifiesRecipient messageRecipient = new SpecifiesRecipient();
        List<Long> list;
        if(Objects.nonNull(internalMessageDTO.getUserNo())){
            list = new ArrayList<>();
            list.add(internalMessageDTO.getUserNo());
        }else{
            list = getPlatformUser(internalMessageDTO.getProductCode());
        }

        if(CollectionUtils.isEmpty(list)){
            log.error("=======================发送站内信的用户列表为空==========================");
            return;
        }
        messageRecipient.setUsers(list);
        message.setMessageRecipient(messageRecipient);


        //向消息中心发送消息
        log.info("站内信发送参数，发送参数：{}", message);
        Result<Object> result = configuredOpenClient.doAction(new MessageAction(message));
        if(result.succeed()){
            log.info("站内信发送成功，发送结果：{}", result);
        }else{
            log.error("站内信发送失败，发送结果：{}", result);
        }

    }



    public List<Long> getPlatformUser(String productCode){
        PageProductUsersParam param = new PageProductUsersParam();
        param.setProductCode(productCode);
        param.setPage(1);
        param.setPageSize(10000);
        log.info("开始查询承运平台下的所有用户信息");
        Result<PageData<PageProductUserVo>> pageDataResult = userFeign.pageProductUsers(param);

        if(pageDataResult.succeed()){
            return pageDataResult.getData().getRecords().stream().map(
                    PageProductUserVo::getUserNo).collect(Collectors.toList());
        }else{
            log.error("结束查询承运平台下的所有用户信息,响应结果：{}", JSON.toJSONString(pageDataResult));
            return null;
        }
    }

    //构建站内信中的内容，替换变量
    private static String replaceContent(String content,List<Object> list){
        int listSize = 0;
        int times = countCharTimes(content, "%s");
        if(CollectionUtils.isNotEmpty(list)){
            listSize = list.size();
        }
        if(times != listSize){
            log.error("替换的变量和字符串中需要的变量数量不一致");
            return null;
        }
        return String.format(content, list.toArray());
    }



}
