package com.cusc.nirvana.user.rnr.fp.service.impl;

import com.alibaba.fastjson.JSON;
import com.cusc.nirvana.common.encrypt.sign.HMAC;
import com.cusc.nirvana.common.loader.StringUtils;
import com.cusc.nirvana.common.result.Response;
import com.cusc.nirvana.user.rnr.fp.common.FpLogOutputJsonSerializeFilter;
import com.cusc.nirvana.user.rnr.fp.config.SimVehicleConfig;
import com.cusc.nirvana.user.rnr.fp.converter.CuFlowConverter;
import com.cusc.nirvana.user.rnr.fp.dto.FlowDernrRequestDTO;
import com.cusc.nirvana.user.rnr.fp.dto.FlowEnterpriseInfoDTO;
import com.cusc.nirvana.user.rnr.fp.dto.FlowExtsDTO;
import com.cusc.nirvana.user.rnr.fp.dto.FlowPersonalInfoDTO;
import com.cusc.nirvana.user.rnr.fp.dto.FlowRnrInfoDTO;
import com.cusc.nirvana.user.rnr.fp.dto.FlowRnrRequestDTO;
import com.cusc.nirvana.user.rnr.fp.dto.FlowSwapDeviceRequestDTO;
import com.cusc.nirvana.user.rnr.fp.dto.FlowVehicleInfoDTO;
import com.cusc.nirvana.user.rnr.fp.dto.FpT1UploadStatusDTO;
import com.cusc.nirvana.user.rnr.fp.service.ICuFlowService;
import com.cusc.nirvana.user.rnr.fp.service.IFpT1UploadStatusService;
import com.cusc.nirvana.user.rnr.fp.util.RnrFpRestTemplateUtils;
import com.cusc.nirvana.user.rnr.mg.client.MgRnrCompanyInfoClient;
import com.cusc.nirvana.user.rnr.mg.client.MgRnrInfoClient;
import com.cusc.nirvana.user.rnr.mg.client.OrgBusinessTagClient;
import com.cusc.nirvana.user.rnr.mg.client.OrgSimRelClient;
import com.cusc.nirvana.user.rnr.mg.client.RnrOrderClient;
import com.cusc.nirvana.user.rnr.mg.constants.CertTypeEnum;
import com.cusc.nirvana.user.rnr.mg.constants.CommonYesOrNoEnum;
import com.cusc.nirvana.user.rnr.mg.constants.CompanyTypeEnum;
import com.cusc.nirvana.user.rnr.mg.constants.RnrBizzTypeEnum;
import com.cusc.nirvana.user.rnr.mg.constants.SystemCodeEnum;
import com.cusc.nirvana.user.rnr.mg.dto.MgCardNoticeDTO;
import com.cusc.nirvana.user.rnr.mg.dto.MgRnrCompanyInfoDTO;
import com.cusc.nirvana.user.rnr.mg.dto.MgRnrInfoDTO;
import com.cusc.nirvana.user.rnr.mg.dto.OrgBusinessTagDTO;
import com.cusc.nirvana.user.rnr.mg.dto.OrgSimRelDTO;
import com.cusc.nirvana.user.rnr.mg.dto.RnrOrderDTO;
import com.cusc.nirvana.user.rnr.project.constant.SignConstants;
import com.cusc.nirvana.user.util.CuscStringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.Date;

/**
 * Description:联通切流service
 * <br />
 * CreateDate 2022-07-28 11:12:21
 *
 * @author yuyi
 **/
@Service
@Slf4j
public class CuFlowServiceImpl implements ICuFlowService {

    @Resource
    private IFpT1UploadStatusService fpT1UploadStatusService;

    @Autowired
    @Qualifier("noBalanceRestTemplateRnrFp")
    private RestTemplate noBalanceRestTemplateRnrFp;

    @Autowired
    private SimVehicleConfig simVehicleConfig;

    @Autowired
    private OrgSimRelClient orgSimRelClient;

    @Autowired
    private OrgBusinessTagClient orgBusinessTagClient;

    @Autowired
    private RnrOrderClient orderClient;

    @Autowired
    private MgRnrInfoClient rnrInfoClient;

    @Autowired
    private MgRnrCompanyInfoClient rnrCompanyInfoClient;

    /**
     * Description: 切流事件
     * <br />
     * CreateDate 2022-07-27 20:35:00
     *
     * @author yuyi
     **/
    @Override
    public Response switchNetwork(MgCardNoticeDTO bean) {
        if (RnrBizzTypeEnum.INFO_CHANGE.getCode().equals(bean.getRnrBizzType()) || bean.getResultCode() != 3) {
            log.info("switchNetwork 不用处理 , param : {}", JSON.toJSONString(bean, new FpLogOutputJsonSerializeFilter()));
            return Response.createSuccess("无需处理");
        }
        FpT1UploadStatusDTO t1UploadStatus = new FpT1UploadStatusDTO();
        t1UploadStatus.setIccid(bean.getIccid());
        t1UploadStatus.setOrderId(bean.getOrderId());
        t1UploadStatus.setTenantNo(bean.getTenantNo());
        t1UploadStatus = fpT1UploadStatusService.insertOrResetFlow(t1UploadStatus);
        log.info("switchNetwork t1UploadStatus : {}", JSON.toJSONString(t1UploadStatus));

        Response ret;
        try {
            //实名
            if (RnrBizzTypeEnum.Bind.getCode().equals(bean.getRnrBizzType())) {
                ret = rnr(bean);
            } else if (RnrBizzTypeEnum.Unbound.getCode().equals(bean.getRnrBizzType())) {
                //解绑
                ret = dernr(bean);
            } else if (RnrBizzTypeEnum.ChangeBinding.getCode().equals(bean.getRnrBizzType())) {
                //换件
                ret = swapDevice(bean);
            } else {
                ret = Response.createSuccess("未知的业务类型");
            }
            if (!ret.isSuccess()) {
                log.warn("switchNetwork请求事件服务未正常返回，request：{}，response：{}", JSON.toJSONString(bean),
                        JSON.toJSONString(ret));
                //防止通知模块重试
                ret = Response.createSuccess(ret.getMsg());
            }
            FpT1UploadStatusDTO fpT1UploadStatusDTO = new FpT1UploadStatusDTO();
            fpT1UploadStatusDTO.setUuid(t1UploadStatus.getUuid());
            fpT1UploadStatusDTO.setFlowStatus(1);
            fpT1UploadStatusDTO.setFlowStatusResp(JSON.toJSONString(ret));
            fpT1UploadStatusService.update(fpT1UploadStatusDTO);
        } catch (Exception e) {
            log.error("switchNetwork error : " + JSON.toJSONString(bean), e);
            ret = Response.createError("系统异常");
        }
        return ret;
    }

    @Override
    public Response rnr(MgCardNoticeDTO bean) {
        //通过iccid查询卡信息
        Response<OrgSimRelDTO> simResp = orgSimRelClient.getByIccid(bean.getIccid());
        if (!simResp.isSuccess()) {
            return simResp;
        }
        OrgSimRelDTO simInfo = simResp.getData();
        if (simInfo == null) {
            return Response.createError("ICCID[" + bean.getIccid() + "]查询卡信息为空");
        }

        //通过工单查询自然人信息
        RnrOrderDTO orderDTO = new RnrOrderDTO();
        orderDTO.setUuid(bean.getOrderId());
        orderDTO.setTenantNo(bean.getTenantNo());
        Response<RnrOrderDTO> orderResp = orderClient.getByUuid(orderDTO);
        if (!orderResp.isSuccess() || orderResp.getData() == null) {
            log.warn("rnr 查询工单信息失败 ： {}", JSON.toJSONString(orderDTO));
            return Response.createError("查询工单信息失败或未查询到工单信息");
        }
        orderDTO = orderResp.getData();

        //通过实名id查询实名信息
        MgRnrInfoDTO rnrInfo = new MgRnrInfoDTO();
        rnrInfo.setUuid(orderDTO.getRnrId());
        rnrInfo.setTenantNo(orderDTO.getTenantNo());
        Response<MgRnrInfoDTO> rnrInfoResp = rnrInfoClient.getByUuid(rnrInfo);
        if (!rnrInfoResp.isSuccess() || rnrInfoResp.getData() == null) {
            log.warn("rnr 查询实名信息失败 ： {}", JSON.toJSONString(rnrInfoResp));
            return Response.createError("查询实名信息失败或未找到实名信息");
        }
        rnrInfo = rnrInfoResp.getData();

        MgRnrCompanyInfoDTO companyInfo = null;
        if (CommonYesOrNoEnum.YES.getCode() == rnrInfo.getIsCompany().intValue()) {
            //通过实名id查询企业信息
            companyInfo = new MgRnrCompanyInfoDTO();
            companyInfo.setRnrId(rnrInfo.getUuid());
            companyInfo.setTenantNo(rnrInfo.getTenantNo());
            Response<MgRnrCompanyInfoDTO> companyInfoResp = rnrCompanyInfoClient.getByRnrid(companyInfo);
            if (!companyInfoResp.isSuccess() || companyInfoResp.getData() == null) {
                log.warn("rnr 查询实名企业信息失败 ： {}", JSON.toJSONString(companyInfoResp));
                return Response.createError("查询实名企业信息失败或未找到实名企业信息");
            }
            companyInfo = companyInfoResp.getData();
        }

        FlowRnrRequestDTO rnrReq = new FlowRnrRequestDTO();
        FlowVehicleInfoDTO vehicleInfoDTO = CuFlowConverter.INSTANCE.vehicleFromOrgSim(simInfo);
        FlowRnrInfoDTO rnrInfoDTO = CuFlowConverter.INSTANCE.rnrFromCardNotice(bean, vehicleInfoDTO);
        rnrReq.setRnrInfos(Arrays.asList(rnrInfoDTO));
        rnrReq.setBizType(transformBizType(rnrInfo, companyInfo));
        rnrReq.setExts(buildFlowExts(1, simInfo.getTagUuid(), rnrInfo, companyInfo));
        return rnrRequest(rnrReq);
    }

    @Override
    public Response dernr(MgCardNoticeDTO bean) {
        //通过iccid查询卡信息
        Response<OrgSimRelDTO> simResp = orgSimRelClient.getByIccid(bean.getIccid());
        if (!simResp.isSuccess()) {
            return simResp;
        }
        OrgSimRelDTO simInfo = simResp.getData();
        if (simInfo == null) {
            return Response.createError("ICCID[" + bean.getIccid() + "]查询卡信息为空");
        }

        //通过工单查询自然人信息
        RnrOrderDTO orderDTO = new RnrOrderDTO();
        orderDTO.setUuid(bean.getOrderId());
        orderDTO.setTenantNo(bean.getTenantNo());
        Response<RnrOrderDTO> orderResp = orderClient.getByUuid(orderDTO);
        if (!orderResp.isSuccess() || orderResp.getData() == null) {
            log.warn("rnr 查询工单信息失败 ： {}", JSON.toJSONString(orderDTO));
            return Response.createError("查询工单信息失败或未查询到工单信息");
        }
        orderDTO = orderResp.getData();

        //通过实名id查询实名信息
        MgRnrInfoDTO rnrInfo = new MgRnrInfoDTO();
        rnrInfo.setUuid(orderDTO.getRnrId());
        rnrInfo.setTenantNo(orderDTO.getTenantNo());
        Response<MgRnrInfoDTO> rnrInfoResp = rnrInfoClient.getByUuid(rnrInfo);
        if (!rnrInfoResp.isSuccess() || rnrInfoResp.getData() == null) {
            log.warn("rnr 查询实名信息失败 ： {}", JSON.toJSONString(rnrInfoResp));
            return Response.createError("查询实名信息失败或未找到实名信息");
        }
        rnrInfo = rnrInfoResp.getData();

        FlowDernrRequestDTO dernrReq = new FlowDernrRequestDTO();
        FlowVehicleInfoDTO vehicleInfoDTO = CuFlowConverter.INSTANCE.vehicleFromOrgSim(simInfo);
        FlowRnrInfoDTO rnrInfoDTO = CuFlowConverter.INSTANCE.rnrFromCardNotice(bean, vehicleInfoDTO);
        dernrReq.setRnrInfos(Arrays.asList(rnrInfoDTO));
        dernrReq.setExts(buildFlowExts(2, simInfo.getTagUuid(), rnrInfo, null));
        return dernrRequest(dernrReq);
    }

    @Override
    public Response swapDevice(MgCardNoticeDTO bean) {
        //通过iccid查询卡信息
        Response<OrgSimRelDTO> simResp = orgSimRelClient.getByIccid(bean.getIccid());
        if (!simResp.isSuccess()) {
            return simResp;
        }
        OrgSimRelDTO simInfo = simResp.getData();
        if (simInfo == null) {
            return Response.createError("ICCID[" + bean.getIccid() + "]查询卡信息为空");
        }

        //通过工单查询自然人信息
        RnrOrderDTO orderDTO = new RnrOrderDTO();
        orderDTO.setUuid(bean.getOrderId());
        orderDTO.setTenantNo(bean.getTenantNo());
        Response<RnrOrderDTO> orderResp = orderClient.getByUuid(orderDTO);
        if (!orderResp.isSuccess() || orderResp.getData() == null) {
            log.warn("rnr 查询工单信息失败 ： {}", JSON.toJSONString(orderDTO));
            return Response.createError("查询工单信息失败或未查询到工单信息");
        }
        orderDTO = orderResp.getData();

        //通过实名id查询实名信息
        MgRnrInfoDTO rnrInfo = new MgRnrInfoDTO();
        rnrInfo.setUuid(orderDTO.getRnrId());
        rnrInfo.setTenantNo(orderDTO.getTenantNo());
        Response<MgRnrInfoDTO> rnrInfoResp = rnrInfoClient.getByUuid(rnrInfo);
        if (!rnrInfoResp.isSuccess() || rnrInfoResp.getData() == null) {
            log.warn("rnr 查询实名信息失败 ： {}", JSON.toJSONString(rnrInfoResp));
            return Response.createError("查询实名信息失败或未找到实名信息");
        }
        rnrInfo = rnrInfoResp.getData();

        FlowDernrRequestDTO dernrReq = new FlowDernrRequestDTO();
        FlowVehicleInfoDTO vehicleInfoDTO = CuFlowConverter.INSTANCE.vehicleFromOrgSim(simInfo);
        FlowRnrInfoDTO rnrInfoDTO = CuFlowConverter.INSTANCE.rnrFromCardNotice(bean, vehicleInfoDTO);
        dernrReq.setRnrInfos(Arrays.asList(rnrInfoDTO));
        dernrReq.setExts(buildFlowExts(2, simInfo.getTagUuid(), rnrInfo, null));

        FlowSwapDeviceRequestDTO swapDeviceReq = new FlowSwapDeviceRequestDTO();
        swapDeviceReq.setVin(bean.getVin());
        swapDeviceReq.setOldIccid(bean.getOldIccid());
        swapDeviceReq.setOldRnrStatus(0);
        swapDeviceReq.setNewIccid(bean.getIccid());
        swapDeviceReq.setNewRnrStatus(1);
        swapDeviceReq.setExts(buildFlowExts(3, simInfo.getTagUuid(), rnrInfo, null));
        return swapDeviceRequest(swapDeviceReq);
    }

    //------------------------------私有方法区域--------------------

    /**
     * Description: 实名事件请求
     * <br />
     * CreateDate 2022-07-28 16:25:02
     *
     * @author yuyi
     **/
    private Response rnrRequest(FlowRnrRequestDTO rnrReq) {
        HttpEntity httpEntity = new HttpEntity(rnrReq, headers());
        try {
            String url = simVehicleConfig.getUrl() + "/notify/rnr";
            return RnrFpRestTemplateUtils.postOpenApiForObject(noBalanceRestTemplateRnrFp, url, httpEntity,
                    Response.class);
        } catch (Exception e) {
            log.error("rnrRequest error : ", e);
            return Response.createError("系统异常");
        }
    }

    /**
     * Description: 解绑事件请求
     * <br />
     * CreateDate 2022-07-28 16:25:02
     *
     * @author yuyi
     **/
    private Response dernrRequest(FlowDernrRequestDTO dernrReq) {
        HttpEntity httpEntity = new HttpEntity(dernrReq, headers());
        try {
            String url = simVehicleConfig.getUrl() + "/notify/dernr";
            return RnrFpRestTemplateUtils.postOpenApiForObject(noBalanceRestTemplateRnrFp, url, httpEntity,
                    Response.class);
        } catch (Exception e) {
            log.error("dernrRequest error : ", e);
            return Response.createError("系统异常");
        }
    }

    /**
     * Description: 换件事件请求
     * <br />
     * CreateDate 2022-07-28 16:25:02
     *
     * @author yuyi
     **/
    private Response swapDeviceRequest(FlowSwapDeviceRequestDTO bean) {
        HttpEntity httpEntity = new HttpEntity(bean, headers());
        try {
            String url = simVehicleConfig.getUrl() + "/notify/swap-device";
            return RnrFpRestTemplateUtils.postOpenApiForObject(noBalanceRestTemplateRnrFp, url, httpEntity,
                    Response.class);
        } catch (Exception e) {
            log.error("swapDeviceRequest error : ", e);
            return Response.createError("系统异常");
        }
    }

    /**
     * 生成请求头
     *
     * @return
     */
    private HttpHeaders headers() {
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.add(SignConstants.APP_ID, simVehicleConfig.getAppId());
        httpHeaders.add(SignConstants.NONCE_STR, CuscStringUtils.generateUuid());
        httpHeaders.add(SignConstants.TIMESTAMP, String.valueOf(new Date().getTime()));
        httpHeaders.add(SignConstants.VERSION, simVehicleConfig.getVersion());
        StringBuilder sb = new StringBuilder();
        sb.append(SignConstants.APP_ID + simVehicleConfig.getAppId());
        sb.append(SignConstants.NONCE_STR + httpHeaders.get(SignConstants.NONCE_STR).get(0));
        sb.append(SignConstants.TIMESTAMP + httpHeaders.get(SignConstants.TIMESTAMP).get(0));
        sb.append(SignConstants.VERSION + simVehicleConfig.getVersion());
        String scret = HMAC.sign(sb.toString(), simVehicleConfig.getAppScret(), HMAC.Type.HmacSHA256);
        httpHeaders.add(SignConstants.SIGN, scret);
        httpHeaders.setContentType(MediaType.parseMediaType("application/json; charset=UTF-8"));
        return httpHeaders;
    }

    /**
     * Description: 构建事件服务的扩展属性
     * eventType ： 1 实名 2 解绑 3换件
     * <br />
     * CreateDate 2022-07-28 22:05:11
     *
     * @author yuyi
     **/
    private FlowExtsDTO buildFlowExts(int eventType, String tagUuid, MgRnrInfoDTO rnrInfo,
                                      MgRnrCompanyInfoDTO companyInfo) {
        FlowExtsDTO ret = new FlowExtsDTO();
        if (StringUtils.isNotBlank(tagUuid)) {
            //通过tagid查询tagcode
            OrgBusinessTagDTO obt = new OrgBusinessTagDTO();
            obt.setTenantNo(rnrInfo.getTenantNo());
            obt.setTagCode(tagUuid);
            Response<OrgBusinessTagDTO> orgBusinessTagDTOResp = orgBusinessTagClient.getByTagCode(obt);
            if (orgBusinessTagDTOResp.isSuccess() && orgBusinessTagDTOResp.getData() != null) {
                if (SystemCodeEnum.OLD_RNR.getCode() == orgBusinessTagDTOResp.getData().getSystemCode()) {
                    ret.setBrandId(orgBusinessTagDTOResp.getData().getTagCode());
                } else {
                    ret.setAbilityUserId(orgBusinessTagDTOResp.getData().getTagCode());
                }
            }
        }

        if (eventType == 3) {
            //换件
            return ret;
        }
        ret.setPersonalInfo(personalFromMgRnrInfo(rnrInfo));
        if (eventType == 1) {
            //实名时增加企业信息
            ret.setEnterpriseInfo(enterpriseFromCompanyInfo(companyInfo));
        }
        return ret;
    }

    /**
     * Description: 业务类型转换
     * <br />
     * CreateDate 2022-07-29 19:41:50
     *
     * @author yuyi
     **/
    private int transformBizType(MgRnrInfoDTO rnrInfo, MgRnrCompanyInfoDTO companyInfo) {
        if (rnrInfo.getRnrBizzType().intValue() == RnrBizzTypeEnum.Bind.getCode()) {
            if (CommonYesOrNoEnum.YES.getCode() == rnrInfo.getIsSecondHandCar().intValue()) {
                //二手车
                return 3;
            }

            if (CommonYesOrNoEnum.NO.getCode() == rnrInfo.getIsCompany().intValue()) {
                //个人
                return 1;
            } else {
                if (companyInfo != null
                        && companyInfo.getIsVehicleCompany().intValue() == CommonYesOrNoEnum.YES.getCode()) {
                    //车企
                    return 2;
                } else {
                    //企业
                    return 4;
                }
            }
        }
        return 0;
    }

    /**
     * Description: 实名信息转个人信息
     * <br />
     * CreateDate 2022-07-29 19:42:03
     *
     * @author yuyi
     **/
    private FlowPersonalInfoDTO personalFromMgRnrInfo(MgRnrInfoDTO rnrInfo) {
        if (rnrInfo == null) {
            return null;
        }
        FlowPersonalInfoDTO personalInfoDTO = new FlowPersonalInfoDTO();
        personalInfoDTO.setName(rnrInfo.getFullName());
        personalInfoDTO.setPhone(rnrInfo.getPhone());
        personalInfoDTO.setCertId(rnrInfo.getCertNumber());
        personalInfoDTO.setCertType(transformCertType(rnrInfo.getCertType()));
        return personalInfoDTO;
    }

    /**
     * Description: 实名企业信息转企业信息
     * <br />
     * CreateDate 2022-07-29 19:42:03
     *
     * @author yuyi
     **/
    private FlowEnterpriseInfoDTO enterpriseFromCompanyInfo(MgRnrCompanyInfoDTO companyInfo) {
        if (companyInfo == null) {
            return null;
        }
        FlowEnterpriseInfoDTO enterpriseInfoDTO = new FlowEnterpriseInfoDTO();
        enterpriseInfoDTO.setName(companyInfo.getCompanyName());
        enterpriseInfoDTO.setComType(transformComType(companyInfo.getCompanyType()));
        enterpriseInfoDTO.setLicenseCode(companyInfo.getCompanyCertNumber());
        enterpriseInfoDTO.setAddress(companyInfo.getCompanyCertAddress());
        return enterpriseInfoDTO;
    }

    /**
     * Description: 证件类型转换
     * <br />
     * 1军官证,2护照,3居民身份证,4警官证,5港澳居民来往内地通行证,6台湾居民来往大陆通行证,7其他
     * CreateDate 2022-07-29 19:40:26
     *
     * @author yuyi
     **/
    private int transformCertType(String certType) {
        if (CertTypeEnum.PLA.getCode().equals(certType)) {
            return 1;
        }
        if (CertTypeEnum.PASSPORT.getCode().equals(certType)) {
            return 2;
        }
        if (CertTypeEnum.IDCARD.getCode().equals(certType)) {
            return 3;
        }
        if (CertTypeEnum.POLICEPAPER.getCode().equals(certType)) {
            return 4;
        }
        if (CertTypeEnum.HKIDCARD.getCode().equals(certType)) {
            return 5;
        }
        if (CertTypeEnum.TAIBAOZHENG.getCode().equals(certType)) {
            return 6;
        }
        return 7;
    }

    /**
     * Description: 公司类型转换
     * <br />
     * CreateDate 2022-07-29 19:51:26
     *
     * @author yuyi
     **/
    private String transformComType(String companyType) {
        if (companyType.equals(CompanyTypeEnum.YXZRGS.getCode())) {
            return "1";
        }
        if (companyType.equals(CompanyTypeEnum.GFYXGS.getCode())) {
            return "2";
        }
        if (companyType.equals(CompanyTypeEnum.GRDZQY.getCode())) {
            return "3";
        }
        if (companyType.equals(CompanyTypeEnum.SYQY.getCode())) {
            return "4";
        }
        if (companyType.equals(CompanyTypeEnum.LYQY.getCode())) {
            return "5";
        }
        return "0";
    }
}
