package com.hzya.frame.sys.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.Method;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.hzya.frame.serviceUtil.ServiceUtil;
import com.hzya.frame.sys.appApi.entity.AppApi;
import com.hzya.frame.sys.appApi.service.IAppApiService;
import com.hzya.frame.sys.entity.EsbReturnEntity;
import com.hzya.frame.sys.entity.EsbSendEntity;
import com.hzya.frame.sysnew.messageManage.dao.ISysMessageManageDao;
import com.hzya.frame.sysnew.messageManage.entity.SysMessageManageEntity;
import com.hzya.frame.sysnew.messageManageDetail.dao.ISysMessageManageDetailDao;
import com.hzya.frame.sysnew.messageManageDetail.entity.SysMessageManageDetailEntity;
import com.hzya.frame.sysnew.messageManageLog.dao.ISysMessageManageLogDao;
import com.hzya.frame.sysnew.messageManageLog.entity.SysMessageManageLogEntity;
import com.hzya.frame.sys.service.IEsbService;
import com.hzya.frame.sys.sysenum.SysEnum;
import com.hzya.frame.uuid.UUIDUtils;
import com.hzya.frame.web.entity.BaseResult;
import com.hzya.frame.web.entity.JsonResultEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.task.TaskExecutor;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;


/**
 * @description: Esb 总线
 */
@Service(value = "esbService")
public class EsbServiceImpl extends ServiceUtil implements IEsbService {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    @Resource
    private TaskExecutor taskExecutor;
    @Resource
    private ISysMessageManageDao sysMessageManageDao;
    @Resource
    private ISysMessageManageDetailDao sysMessageManageDetailDao;
    @Resource
    private ISysMessageManageLogDao sysMessageManageLogDao;
    @Resource
    private IAppApiService appApiService;
    public static final String AUTHPORT = SysEnum.AUTHPORT.getValue();//授权参数
    public static final String EXAMPLE = SysEnum.EXAMPLE.getValue();//示例值
    public static final String PARAMETERNAME = SysEnum.PARAMETERNAME.getValue();
    public static final String PARAMETERTYPE = SysEnum.PARAMETERTYPE.getValue();
    /**
     * @Author lvleigang
     * @Description  ESB总线
     * @Date 9:16 上午 2023/8/30
     * @param object
     * @return com.hzya.frame.web.entity.JsonResultEntity
     **/
    @Override
    public JsonResultEntity doESB(JSONObject object) {
        EsbSendEntity entity = getData("jsonStr", object, EsbSendEntity.class);
        //判断发送者编码
        if(entity == null || entity.getSendCode() == null || entity.getSendCode() == null){
            return BaseResult.getFailureMessageEntity("发送者编码不允许为空");
        }
        //根据发送者编码查询数据
        SysMessageManageEntity messageManageEntity = new SysMessageManageEntity();
        messageManageEntity.setCode(entity.getSendCode());
        messageManageEntity.setSts("Y");
        List<SysMessageManageEntity> manageEntities = sysMessageManageDao.queryBase(messageManageEntity);
        //判断发送者编码是否存在
        if(manageEntities == null || manageEntities.size() != 1 ){
            return BaseResult.getFailureMessageEntity("发送者编码查询错误");
        }
        messageManageEntity = manageEntities.get(0);
        if(messageManageEntity.getDataType() == null
                || !"1".equals(messageManageEntity.getDataType())
                || !"2".equals(messageManageEntity.getDataType())){
            return BaseResult.getFailureMessageEntity("消息管理数据类型错误");
        }
        if(messageManageEntity.getSendApi() == null || "".equals(messageManageEntity.getSendApi())){
            return BaseResult.getFailureMessageEntity("消息管理发送者错误");
        }
        //根据消息管理查询消息管理的明细配置
        SysMessageManageDetailEntity manageDetailEntity = new SysMessageManageDetailEntity();
        manageDetailEntity.setFormmainId(messageManageEntity.getId());
        manageDetailEntity.setReceiveCode(entity.getReceiveCode());
        manageDetailEntity.setSts("Y");
        List<SysMessageManageDetailEntity> manageDetailEntities = sysMessageManageDetailDao.queryBase(manageDetailEntity);
        if(entity.getReceiveCode() != null && !"".equals(entity.getReceiveCode())){
            //判断接收者编码是否存在
            if(manageDetailEntities == null || manageDetailEntities.size() != 1 ){
                return BaseResult.getFailureMessageEntity("接收者编码查询错误");
            }
        }else {
            if(manageDetailEntities == null || manageDetailEntities.size() == 0 ){
                return BaseResult.getFailureMessageEntity("未配置消息管理接收方");
            }
        }
        List<SysMessageManageLogEntity> manageLogEntities = saveToLog(entity,messageManageEntity,manageDetailEntities);
        //异步执行
        taskExecutor.execute(() -> doEsbTask(manageLogEntities));
        return BaseResult.getSuccessMessageEntity("ESB执行中请稍后查看任务状态");
    }



    /**
     * @Author lvleigang
     * @Description  ESB总线——第三方不需要本系统登陆
     * @Date 9:16 上午 2023/8/30
     * @param object
     * @return com.hzya.frame.web.entity.JsonResultEntity
     **/
    @Override
    public JsonResultEntity thirdInterfaceDoESB(JSONObject object) {
        EsbSendEntity entity = getData("jsonStr", object, EsbSendEntity.class);
        //判断发送者编码
        if(entity == null || entity.getSendCode() == null || entity.getSendCode() == null){
            return BaseResult.getFailureMessageEntity("发送者编码不允许为空");
        }
        //根据发送者编码查询数据
        SysMessageManageEntity messageManageEntity = new SysMessageManageEntity();
        messageManageEntity.setCode(entity.getSendCode());
        messageManageEntity.setSts("Y");
        List<SysMessageManageEntity> manageEntities = sysMessageManageDao.queryBase(messageManageEntity);
        //判断发送者编码是否存在
        if(manageEntities == null || manageEntities.size() != 1 ){
            return BaseResult.getFailureMessageEntity("发送者编码查询错误");
        }
        messageManageEntity = manageEntities.get(0);
        if(messageManageEntity.getDataType() == null
                || (!"1".equals(messageManageEntity.getDataType())
                && !"2".equals(messageManageEntity.getDataType()))){
            return BaseResult.getFailureMessageEntity("消息管理数据类型错误");
        }
        if(messageManageEntity.getSendApi() == null || "".equals(messageManageEntity.getSendApi())){
            return BaseResult.getFailureMessageEntity("消息管理发送者错误");
        }
        //根据消息管理查询消息管理的明细配置
        SysMessageManageDetailEntity manageDetailEntity = new SysMessageManageDetailEntity();
        manageDetailEntity.setFormmainId(messageManageEntity.getId());
        manageDetailEntity.setReceiveCode(entity.getReceiveCode());
        manageDetailEntity.setSts("Y");
        List<SysMessageManageDetailEntity> manageDetailEntities = sysMessageManageDetailDao.queryBase(manageDetailEntity);
        if(entity.getReceiveCode() != null && !"".equals(entity.getReceiveCode())){
            //判断接收者编码是否存在
            if(manageDetailEntities == null || manageDetailEntities.size() != 1 ){
                return BaseResult.getFailureMessageEntity("接收者编码查询错误");
            }
        }else {
            if(manageDetailEntities == null || manageDetailEntities.size() == 0 ){
                return BaseResult.getFailureMessageEntity("未配置消息管理接收方");
            }
        }
        //设置登陆人
        if(!StpUtil.isLogin()){
            StpUtil.login("c796fd9ba4c9f5ff3cc2fa41a040e443");
        }
        List<SysMessageManageLogEntity> manageLogEntities = saveToLog(entity,messageManageEntity,manageDetailEntities);
        taskExecutor.execute(() -> doEsbTask(manageLogEntities));
        return BaseResult.getSuccessMessageEntity("ESB执行中请稍后查看任务状态");
    }



    /**
     * @Author lvleigang
     * @Description  保存日志表
     * @Date 11:12 上午 2023/8/30
     * @param entity
     * @param messageManageEntity
     * @param manageDetailEntities
     * @return java.util.List<com.hzya.frame.sys.messageManageLog.entity.SysMessageManageLogEntity>
     **/
    private List<SysMessageManageLogEntity> saveToLog(EsbSendEntity entity, SysMessageManageEntity messageManageEntity, List<SysMessageManageDetailEntity> manageDetailEntities) {
        List<SysMessageManageLogEntity> manageLogEntities = new ArrayList<>();
        List<JSONObject> sendData = new ArrayList<>();
        //根据消息管理主表的数据类型拆分数据
        if("1".equals(messageManageEntity.getDataType() )){//1、对象
            JSONObject jsonObject = JSON.parseObject(entity.getSourceData());
            sendData.add(jsonObject);
        }else {// 2、数组
            JSONArray jsonArray = JSONArray.parseArray(entity.getSourceData());
            sendData.addAll(jsonArray.toJavaList(JSONObject.class));
        }
        //根据明细表的配置，设置组装数据
        if(manageDetailEntities != null && manageDetailEntities.size() > 0 &&
                sendData != null && sendData.size() > 0){
            for (int i = 0; i < manageDetailEntities.size(); i++) {
                if("1".equals(manageDetailEntities.get(i).getDataType() )){//1、对象
                    for (int i1 = 0; i1 < sendData.size(); i1++) {
                        SysMessageManageLogEntity sysMessageManageLogEntity = new SysMessageManageLogEntity();
                        sysMessageManageLogEntity.setMessageManageId(messageManageEntity.getId());//消息主表主键
                        sysMessageManageLogEntity.setTheme(messageManageEntity.getTheme());//消息主题
                        sysMessageManageLogEntity.setMessageCode(messageManageEntity.getCode());//消息编码
                        sysMessageManageLogEntity.setSendApp(messageManageEntity.getSendApp());//发送者应用
                        sysMessageManageLogEntity.setSendApi(messageManageEntity.getSendApi());//发送者
                        sysMessageManageLogEntity.setReceiveCode(manageDetailEntities.get(i).getReceiveCode());//接收者编码
                        sysMessageManageLogEntity.setReceiveApp(manageDetailEntities.get(i).getReceiveApp());//接收者应用
                        sysMessageManageLogEntity.setReceiveApi(manageDetailEntities.get(i).getReceiveApi());//接收者
                        sysMessageManageLogEntity.setReturnType(manageDetailEntities.get(i).getReturnType());//返回解析类型
                        sysMessageManageLogEntity.setSourceData(sendData.get(i).toString());//源数据
                        sysMessageManageLogEntity.setStatus("1");//状态（1、待发送 2、发送中3、发送成功 4、发送失败）
                        sysMessageManageLogEntity.setRemark("待发送");//备注
                        sysMessageManageLogEntity.setId(UUIDUtils.getUUID());
                        sysMessageManageLogEntity.setCreate_user_id(StpUtil.getLoginIdAsString());
                        sysMessageManageLogEntity.setModify_user_id(StpUtil.getLoginIdAsString());
                        sysMessageManageLogEntity.setCreate_time(new Date());
                        sysMessageManageLogEntity.setModify_time(new Date());
                        sysMessageManageLogEntity.setSts("Y");
                        manageLogEntities.add(sysMessageManageLogEntity);

                    }
                }else {// 2、数组
                    for (int i1 = 0; i1 < sendData.size(); i1++) {
                        SysMessageManageLogEntity sysMessageManageLogEntity = new SysMessageManageLogEntity();
                        sysMessageManageLogEntity.setMessageManageId(messageManageEntity.getId());//消息主表主键
                        sysMessageManageLogEntity.setTheme(messageManageEntity.getTheme());//消息主题
                        sysMessageManageLogEntity.setMessageCode(messageManageEntity.getCode());//消息编码
                        sysMessageManageLogEntity.setSendApp(messageManageEntity.getSendApp());//发送者应用
                        sysMessageManageLogEntity.setSendApi(messageManageEntity.getSendApi());//发送者
                        sysMessageManageLogEntity.setReceiveCode(manageDetailEntities.get(i).getReceiveCode());//接收者编码
                        sysMessageManageLogEntity.setReceiveApp(manageDetailEntities.get(i).getReceiveApp());//接收者应用
                        sysMessageManageLogEntity.setReceiveApi(manageDetailEntities.get(i).getReceiveApi());//接收者
                        sysMessageManageLogEntity.setSourceData(sendData.get(i).toString());//源数据
                        sysMessageManageLogEntity.setReturnType(manageDetailEntities.get(i).getReturnType());//返回解析类型
                        sysMessageManageLogEntity.setStatus("1");//状态（1、待发送 2、发送中3、发送成功 4、发送失败）
                        sysMessageManageLogEntity.setRemark("待发送");//备注
                        sysMessageManageLogEntity.setId(UUIDUtils.getUUID());
                        sysMessageManageLogEntity.setCreate_user_id(StpUtil.getLoginIdAsString());
                        sysMessageManageLogEntity.setModify_user_id(StpUtil.getLoginIdAsString());
                        sysMessageManageLogEntity.setCreate_time(new Date());
                        sysMessageManageLogEntity.setModify_time(new Date());
                        sysMessageManageLogEntity.setSts("Y");
                        manageLogEntities.add(sysMessageManageLogEntity);
                    }
                }
            }
        }

        //保存数据到日志表中
        if(manageLogEntities != null && manageLogEntities.size() > 0){
            for (int i = 0; i < manageLogEntities.size(); i++) {
                sysMessageManageLogDao.save(manageLogEntities.get(i));
            }
        }
        return manageLogEntities;
    }

    /**
     * @Author lvleigang
     * @Description 单个发送 具体执行发送任务
     * @Date 11:18 上午 2023/8/30
     * @param entity
     * @return void
     **/
    @Override
    public boolean doEsbTaskOne(SysMessageManageLogEntity entity) {
        JSONObject sendData = JSONObject.parseObject(entity.getSourceData());//源数据
        JSONObject entityData = (JSONObject) JSONObject.toJSON(entity);//源数据
        //修改日志状态
        updateLog(entity.getId(),null,null,"2","发送中");
        //查询接收者接口api
        AppApi appApi = appApiService.getByid(entity.getReceiveApi());
        try {
            String returnData = getToSendData(appApi,sendData,entity.getReturnType());
            //判断返回是否成功
            if(JSONUtil.isTypeJSONObject(returnData)){
                EsbReturnEntity esbReturnEntity = JSON.parseObject(returnData,EsbReturnEntity.class);
                if(esbReturnEntity != null){
                    if(esbReturnEntity.getLogType()){//日志类型 空或者false不保存 、true 保存
                        if(esbReturnEntity.getStatus()){
                            updateLog(entity.getId(),esbReturnEntity.getTargetData(),esbReturnEntity.getReturnData(),"3",esbReturnEntity.getRemark());//状态（1、待发送 2、发送中3、发送成功 4、发送失败）
                            return true;
                        }else {
                            updateLog(entity.getId(),esbReturnEntity.getTargetData(),esbReturnEntity.getReturnData(),"4",esbReturnEntity.getRemark());//状态（1、待发送 2、发送中3、发送成功 4、发送失败）
                        }
                    }
                }else {
                    //当返回为空的时候不添加日志
                    //updateLog(entity.getId(),null,null,"4","发送失败:：返回数据格式错误");//状态（1、待发送 2、发送中3、发送成功 4、发送失败）
                }
            }else {
                //当返回为空的时候不添加日志
                //updateLog(entity.getId(),null,null,"4","发送失败:：返回数据格式错误");//状态（1、待发送 2、发送中3、发送成功 4、发送失败）
            }
        } catch (Exception e) {
            logger.error("数据发送错误！：对象：{} ，错误信息：{}",entityData.toString(),e.getMessage());
            updateLog(entity.getId(),null,null,"4","发送失败:："+e.getMessage());//状态（1、待发送 2、发送中3、发送成功 4、发送失败）
        }
        return false;
    }

    /**
     * @Author lvleigang
     * @Description  发送数据
     * @Date 8:44 上午 2023/8/31
     * @param appApi 当前api
     * @param sendData 发送的参数，有的取值没有的去实例
     * @return java.lang.String
     **/
    private String getToSendData(AppApi appApi, JSONObject sendData ,String returnType) throws Exception{
        JSONObject loginData = new JSONObject();
        //判断是否需要登陆
        if (SysEnum.NEED_LOGIN.getValue().equals(appApi.getNeedLogin())) {
            //找到登陆接口
            AppApi loginApi = appApiService.getByid(appApi.getAuthenticationPort());
            if (null != loginApi) {
                String returnData = getToSendData(loginApi,sendData,null);
                if(returnData != null && !"".equals(returnData) && JSON.isValidObject(returnData)){
                    loginData = JSONObject.parseObject(returnData);
                }
            }
        }
        //构造接口
        //获取query参数
        String querys = appApi.getQuery(sendData,loginData);
        HttpRequest httpRequest = HttpRequest.of(appApi.getDestinationAddress()+querys);
        httpRequest.method(Method.valueOf(appApi.getRequestMethod().toUpperCase()));

        Map<String, String> headers = appApi.getHeaders(sendData,loginData);
        if(headers != null && headers.size() > 0 ){
            httpRequest.addHeaders(headers);//如果原数据有header需要参数就配置
        }

        String bodys = appApi.getBodys(sendData,loginData);
        if(bodys != null && !"".equals(bodys) ){
            httpRequest.body(bodys,"application/json");//如果原数据有body需要参数就配置
        }
        String returnRes = httpRequest.timeout(Integer.valueOf(appApi.getTimeoutPeriod())).execute().body();
        String changeReturn = doChangeReturn(returnRes,returnType,bodys,headers,querys);
        return changeReturn;
    }

    /**
     * @Author lvleigang
     * @Description  解析返回
     * @Date 9:12 上午 2023/9/20
     * @param returnRes
     * @param returnType
     * @return java.lang.String
     **/
    private String doChangeReturn(String returnRes, String returnType, String bodys,Map<String, String> headers,String querys) {
        if(returnType != null && !"".equals(returnType)){
            EsbReturnEntity esbReturnEntity = null;
            JSONObject re = new JSONObject();
            re.put("header", headers);
            re.put("query", querys);
            re.put("body", JSONObject.parseObject(bodys));
            esbReturnEntity = new EsbReturnEntity();
            esbReturnEntity.setReturnData(returnRes);
            esbReturnEntity.setTargetData(re.toString());
            JSONObject sendData = JSONObject.parseObject(returnRes);//源数据
            switch (returnType) {
                case "1"://bip
                    if(sendData.getString("flag") != null && !"".equals(sendData.getString("flag")) && sendData.getBoolean("flag")){
                        JSONObject attribute = JSONObject.parseObject(sendData.getString("attribute"));//源数据
                        if(attribute.getString("success") != null && !"".equals(attribute.getString("success")) && attribute.getBoolean("success")){
                            esbReturnEntity.setStatus(true);
                            esbReturnEntity.setRemark("处理成功");
                        }else {
                            esbReturnEntity.setStatus(false);
                            esbReturnEntity.setRemark(attribute.getString("message"));
                        }
                    }else {
                        esbReturnEntity.setStatus(false);
                        esbReturnEntity.setRemark("处理失败");
                    }
                    esbReturnEntity.setLogType(true);
                    break;
                case "2"://中台bip
                    if(sendData.getString("status") != null && !"".equals(sendData.getString("status"))){
                        if("success".equals(sendData.getString("status"))){
                            esbReturnEntity.setStatus(true);
                            esbReturnEntity.setRemark("处理成功");
                        }else {
                            esbReturnEntity.setStatus(false);
                            esbReturnEntity.setRemark(sendData.getString("errormsg"));
                        }
                    }else {
                        esbReturnEntity.setStatus(false);
                        esbReturnEntity.setRemark("处理失败");
                    }
                    esbReturnEntity.setLogType(true);
                    break;
                default:
                    esbReturnEntity = new EsbReturnEntity();
                    esbReturnEntity.setRemark("返回解析类型未配置");
                    esbReturnEntity.setStatus(false);
                    esbReturnEntity.setLogType(true);
            }
            return JSON.toJSONString(esbReturnEntity);
        }else {
            return returnRes;
        }
    }

    /**
     * @Author lvleigang
     * @Description  body参数 如果源数据有值，用源数据值
     * @Date 5:00 下午 2023/8/30
     * @param bodyStr
     * @param sendData
     * @return java.lang.String
     **/
    private String getBodys(String bodyStr,JSONObject sendData) {
        if (StrUtil.isNotEmpty(bodyStr)) {
            if (JSONUtil.isTypeJSONArray(bodyStr)) {
                JSONObject bodyParam = new JSONObject(new LinkedHashMap<>());
                JSONArray bodyArray = JSON.parseArray(bodyStr);
                for (int i = 0; i < bodyArray.size(); i++) {
                    JSONObject body = (JSONObject) bodyArray.get(i);
                    String parameterType = body.getString(PARAMETERTYPE);
                    if (!AUTHPORT.equals(parameterType)) {//判断body中是否包含认证参数
                        bodyParam.put(body.getString(PARAMETERNAME), body.getString(EXAMPLE));
                    } else {//如有存在认证参数，特殊处理
                        JSONObject authport = new JSONObject();
                        authport.put(body.getString(PARAMETERNAME), body.getString(EXAMPLE));
                        bodyParam.put(AUTHPORT, authport);
                    }
                }
                return bodyParam.toJSONString();
            }
        }
        return null;
    }

    /**
     * @Author lvleigang
     * @Description  修改日志状态和参数
     * @Date 4:30 下午 2023/8/30
     * @param id
     * @param targetData 目标data
     * @param returnData 返回信息
     * @param status 状态（1、待发送 2、发送中3、发送成功 4、发送失败）
     * @param remark 备注
     * @return void
     **/
    private void updateLog(String id, String targetData, String returnData, String status, String remark) {
        SysMessageManageLogEntity sysMessageManageLogEntity = new SysMessageManageLogEntity();
        sysMessageManageLogEntity.setId(id);
        sysMessageManageLogEntity.setTargetData(targetData);
        sysMessageManageLogEntity.setReturnData(returnData);
        sysMessageManageLogEntity.setStatus(status);
        sysMessageManageLogEntity.setRemark(remark);
        sysMessageManageLogDao.update(sysMessageManageLogEntity);
    }


    /**
     * @Author lvleigang
     * @Description  具体执行发送任务
     * @Date 11:43 上午 2023/8/30
     * @param manageLogEntities
     * @return void
     **/
    private void doEsbTask(List<SysMessageManageLogEntity> manageLogEntities) {
        if(manageLogEntities != null && manageLogEntities.size() > 0){
            for (int i = 0; i < manageLogEntities.size(); i++) {
                doEsbTaskOne(manageLogEntities.get(i));
            }
        }
    }
}
