package com.muchinfo.mtp3century.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.muchinfo.mtp.proto.BankMI1;
import com.muchinfo.mtp.proto.Common;
import com.muchinfo.mtp3century.service.IBankAccountSignService;
import com.muchinfo.mtp3century.service.ICommonService;
import com.muchinfo.mtp3century.utils.AjaxResult;
import com.muchinfo.mtp3century.utils.RedisServiceUtil;
import com.muchinfo.mtp3common.enumtype.Constants;
import com.muchinfo.mtp3common.enumtype.FunCodeConstants;
import com.muchinfo.mtp3common.enumtype.MessageType;
import com.muchinfo.mtp3common.enumtype.SysConstants;
import com.muchinfo.mtp3common.utils.*;
import com.muchinfo.mtp3common.vo.*;
import com.muchinfo.mtp3interface.mapper.*;
import com.muchinfo.mtp3pojos.entity.*;
import com.muchinfo.mtp3pojos.vo.ProtoErrorCodes;
import com.muchinfo.mtp3pojos.vo.bankaccountsign.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;

@Service
public class BankAccountSignServiceImpl implements IBankAccountSignService {
    private final Logger log = LoggerFactory.getLogger(this.getClass());
    @Resource
    private IBankAccountsignMapper iBankAccountsignMapper;
    @Resource
    private ISystemmanagerMapper iSystemmanagerMapper;
    @Resource
    private ICommonService iCommonService;
    @Resource
    private IBankAccountoutinapplyMapper iBankAccountoutinapplyMapper;
    @Resource
    private RedisServiceUtil redisServiceUtil;
    @Resource
    private ITaaccountMapper iTaaccountMapper;
    @Resource
    private IUseraccountMapper iUseraccountMapper;
    @Resource
    private IUserinfoMapper iUserinfoMapper;
    @Resource
    private RabbitTemplate rabbitTemplate;
    @Resource
    private IEnumdicitemMapper iEnumdicitemMapper;
    @Resource
    private ISystemmanagerlogMapper iSystemmanagerlogMapper;
    @Resource
    private IBankCusbankinfoMapper iBankCusbankinfoMapper;
    @Resource
    private IBankBankinfoMapper iBankBankinfoMapper;


    @Override
    public PageResult<AccountSignQueryResult> query(AccountSignQueryParam accountSignQueryParam,HttpServletRequest request) {
        IPage<AccountSignQueryResult> page = new Page<>(accountSignQueryParam.getPageNum(), accountSignQueryParam.getPageSize());
        IPage<AccountSignQueryResult> queryResultIPage = iBankAccountsignMapper.selectByParam(page, accountSignQueryParam);
        PageResult<AccountSignQueryResult> pageResult = new PageResult<>();
        pageResult.setCode(Constants.Success_Code_Design);
        pageResult.setMessage(AjaxResult.dealMsg(MessageType.MESSAGE_CODE_SYSTEM001.getCode(), request.getHeader("Accept-Language")));
        pageResult.setPages(queryResultIPage.getPages());
        pageResult.setCurrent(queryResultIPage.getCurrent());
        pageResult.setTotal(queryResultIPage.getTotal());
        pageResult.setPageSize(queryResultIPage.getSize());
        pageResult.setData(queryResultIPage.getRecords());
        return pageResult;
    }

    @Override
    public PageResult<PutOrInAmountQueryResult> queryPutOrIn(PutOrInAmountQueryParam param, HttpServletRequest request) {
        Systemmanager systemmanager = iSystemmanagerMapper.selectOne(new QueryWrapper<Systemmanager>().eq("LOGINCODE", iCommonService.getUserLoginCode(request)));
        if (systemmanager.getReletype() == 1) {
            // 平台，设置areauser 为 null
            param.setAreauserid(null);
        } else {
            param.setAreauserid(systemmanager.getAreauserid());
        }
        IPage<PutOrInAmountQueryResult> page = new Page<>(param.getPageNum(), param.getPageSize());
        IPage<PutOrInAmountQueryResult> resultIPage = iBankAccountoutinapplyMapper.queryPutOrIn(page, param);
        PageResult<PutOrInAmountQueryResult> pageResult = new PageResult<>();
        pageResult.setCode(Constants.Success_Code_Design);
        pageResult.setMessage(AjaxResult.dealMsg(MessageType.MESSAGE_CODE_SYSTEM001.getCode(), request.getHeader("Accept-Language")));
        pageResult.setPages(resultIPage.getPages());
        pageResult.setCurrent(resultIPage.getCurrent());
        pageResult.setTotal(resultIPage.getTotal());
        pageResult.setPageSize(resultIPage.getSize());
        pageResult.setData(resultIPage.getRecords());
        return pageResult;
    }

    @Override
    public AjaxResult<PutOrInAmountQueryResultDetail> queryPutOrInDetail(String accountcode, String cusbankid, String tradedate, String exchticket, HttpServletRequest request) {
        PutOrInAmountQueryResultDetail resultDetail = iBankAccountoutinapplyMapper.queryById(accountcode, cusbankid, tradedate, exchticket);
        if (StringUtils.isNotBlank(resultDetail.getExtendinfo())) {
            BankSignExtendInfo info = JSON.parseObject(resultDetail.getExtendinfo(), BankSignExtendInfo.class);
            if (info.getCertificate_photo_url() != null && info.getCertificate_photo_url().trim().isEmpty()) {
                info.setCertificate_photo_url(null);
            }
            resultDetail.setBankSignExtendInfo(info);
        }
        return AjaxResult.success(Constants.Success_Code_Design, MessageType.MESSAGE_CODE_SYSTEM001.getCode(), request.getHeader("Accept-Language"), resultDetail);
    }

    @Override
    public AjaxResult queryPutOrInExport(PutOrInAmountQueryParam param, HttpServletRequest request) {
        try {
            String fileName = "出入金查询_" + DateTimeUtils.getDateTime("yyyyMMdd");
            Systemmanager systemmanager = iSystemmanagerMapper.selectOne(new QueryWrapper<Systemmanager>().eq("LOGINCODE", iCommonService.getUserLoginCode(request)));
            if (systemmanager.getReletype() == 1) {
                // 平台，设置areauser 为 null
                param.setAreauserid(null);
            } else {
                param.setAreauserid(systemmanager.getAreauserid());
            }
            List<PutOrInAmountQueryResult> results = iBankAccountoutinapplyMapper.queryPutOrIn(param);
            ExportResult exportResult = ExportUtil.write(fileName, PutOrInAmountQueryResult.class, results);
            return AjaxResult.success(Constants.Success_Code_Design, MessageType.MESSAGE_CODE_SYSTEM001.getCode(), request.getHeader("Accept-Language"), exportResult);
        } catch (Exception e) {
            log.error("出入金查询导出失败，失败原因：" + Arrays.toString(e.getStackTrace()));
            return AjaxResult.error(Constants.Error_Code_Design, MessageType.MESSAGE_ERROR_CODE_SYSTEM002.getCode(), request.getHeader("Accept-Language"));
        }
    }

    @Override
    public AjaxResult<BankAccountsignResult> getSignBankById(String accountcode, String cusbankid, String applyexchticket, HttpServletRequest request) {
        BankAccountsignResult result = new BankAccountsignResult();
        BankAccountsign bankAccountsign = iBankAccountsignMapper.selectOne(new QueryWrapper<BankAccountsign>()
                .eq(StringUtils.isNotBlank(accountcode), "ACCOUNTCODE", accountcode)
                .eq(StringUtils.isNotBlank(cusbankid), "CUSBANKID", cusbankid)
                .eq(StringUtils.isNotBlank(applyexchticket), "APPLYEXCHTICKET", applyexchticket)
        );
        BankCusbankinfo cus = iBankCusbankinfoMapper.selectOne(new QueryWrapper<BankCusbankinfo>().eq("cusbankid", bankAccountsign.getCusbankid()));

        bankAccountsign.setCusbankname(cus.getCusbankname());
        bankAccountsign.setBankname(iBankBankinfoMapper.selectOne(new QueryWrapper<BankBankinfo>().eq("BANKID", bankAccountsign.getBankid())).getBankname());
        result.setBankAccountsign(bankAccountsign);
        //处理扩展信息
        String ei = bankAccountsign.getExtendinfo();
        if (StringUtils.isNotBlank(ei)) {
            BankSignExtendInfo info = JSONObject.parseObject(ei, BankSignExtendInfo.class);
            result.setExtendInfo(info);
        }
        //是否可修改手机号
        result.setCanmodifyphone(cus.getCanmodifyphone());
        //是否可修改签约信息 ---银行卡
        result.setCanmodifysigninfo(cus.getCanmodifysigninfo());

        return AjaxResult.success(Constants.Success_Code_Design, MessageType.MESSAGE_CODE_SYSTEM001.getCode(), request.getHeader("Accept-Language"), result);
    }

    @Override
    public AjaxResult dealAccountSign(HttpServletRequest request, AccountSignParam sign) {
        Systemmanager systemmanager = iSystemmanagerMapper.selectOne(new QueryWrapper<Systemmanager>().eq("LOGINCODE", iCommonService.getUserLoginCode(request)));
        Map<String, Object> result = new HashMap<String, Object>();
        Long uuid = SerialNumberUtils.getNewSerialNumber(SerialNumberUtils.prefix_bank);

        Calculator ca = new Calculator(uuid);
        SerialNumberUtils.lockMap.put(uuid, ca);

        if (sign.getType() == 0) {
            //签约 修改 解绑 绑卡    Operatetype 1-增加; 2-修改; 4-绑卡; 5-解绑; 6-换卡]
            //签约信息修改   调用签约相同接口 变更类型固定为2(operatetype)
            BankAccountsign bankaccountsign = iBankAccountsignMapper.selectOne(new QueryWrapper<BankAccountsign>()
                    .eq("accountcode", sign.getAccountcode())
                    .eq("cusbankid", sign.getCusbankid()));

            Integer operatetype = sign.getOperatetype();
            if (operatetype == null) {
                operatetype = 1;
            } else if (operatetype > 2) {
                BeanUtils.copyProperties(bankaccountsign, sign);
            }

            BankMI1.t2bBankSignReq.Builder builder = BankMI1.t2bBankSignReq.newBuilder();
            Common.MessageHead.Builder hd = Common.MessageHead.newBuilder();
            hd.setAccountID(Long.parseLong(sign.getAccountcode()));
            hd.setFunCode(FunCodeConstants.FunCode_Trade_t2bBankSignReq);
            builder.setHeader(hd);
            builder.setTradeDate(DateTimeUtils.format(new Date(), DateTimeUtils.DATE_CHAR_PATTERN));
            builder.setExtOperatorID(uuid);
            String manageid = redisServiceUtil.getCacheMapValue(Constants.REDIS_HEADER_SYSPARAM, "001");
            builder.setExchId(manageid);
            builder.setAccountCode(sign.getAccountcode());
            Taaccount ta = iTaaccountMapper.selectOne(new QueryWrapper<Taaccount>().eq("ACCOUNTID", Long.valueOf(sign.getAccountcode())));
            // 换为userinfo表的customername签约 -20231031 - dyp
            Useraccount ua = iUseraccountMapper.selectOne(new QueryWrapper<Useraccount>().eq("userid", ta.getUserid()));
            //builder.setAccountName(ua.getAccountname());
            Userinfo ui = iUserinfoMapper.selectOne(new QueryWrapper<Userinfo>().eq("userid", ta.getUserid()));
            builder.setAccountName(ui.getCustomername());

            builder.setCusBankID(sign.getCusbankid());
            builder.setOperateType(operatetype);
            builder.setIsForce(sign.getIsforce() == null ? 0 : sign.getIsforce());
            if (ta.getCurrencyid() != null) {
                Enumdicitem item = iEnumdicitemMapper.selectOne(new QueryWrapper<Enumdicitem>()
                        .eq("enumdiccode", "currency")
                        .eq("enumitemname", Long.valueOf(ta.getCurrencyid())));
                builder.setCurrency(item == null ? "" : item.getBankmappedvalue());
            }
            //转换代码
            builder.setTradeDate(DateTimeUtils.format(new Date(), DateTimeUtils.DATE_CHAR_PATTERN));
            builder.setAccountType(sign.getAccounttype());
            // 添加bankaccounttype赋值 20231031 - dyp
            builder.setBankAccountType(sign.getAccounttype());
            builder.setOpenBankAccId(StringUtils.isNotBlank(sign.getOpenbankaccid()) ? sign.getOpenbankaccid() : "");

            if (sign.getIsforce() != null && sign.getIsforce() == 1) {
                builder.setForceSignBankAccountNo(sign.getForcesignbankaccountno());
            }
            if (operatetype > 2) {
                //解密
                builder.setBankAccountNo(EncryptionUtils.decryptForAES(bankaccountsign.getBankaccountno()));
                builder.setBankAccountName(EncryptionUtils.decryptForAES(bankaccountsign.getBankaccountname()));
                builder.setCertID(EncryptionUtils.decryptForAES(bankaccountsign.getCardno()));
                builder.setCertType(bankaccountsign.getCardtype());
                builder.setMobilePhone(EncryptionUtils.decryptForAES(sign.getMobilephone()));
            } else {
                builder.setBankAccountNo(sign.getBankaccountno().trim());
                builder.setBankAccountName(sign.getBankaccountname().trim());
                builder.setCertID(sign.getCertid() != null ? sign.getCertid() : "");
                builder.setCertType(sign.getCerttype() != null ? String.valueOf(sign.getCerttype()) : "");
                builder.setMobilePhone(sign.getMobilephone());
            }

            builder.setExBankName(StringUtils.isNotBlank(sign.getExbankname()) ? sign.getExbankname() : "");
            if (StringUtils.isNotBlank(sign.getOpenbankname())) {
                builder.setOpenBankNo(sign.getOpenbankname());
            }
            if (StringUtils.isNotBlank(sign.getBankprovince())) {
                builder.setBankProvince(sign.getBankprovince());
            }
            if (StringUtils.isNotBlank(sign.getBankcity())) {
                builder.setBankCity(sign.getBankcity());
            }

            //   扩展信息
            BankSignExtendInfo extendinfo = sign.getExtend();
            if (extendinfo != null) {
                if (ua.getUsertype() != 1) {
                    extendinfo.setUser_code(ua.getUserid().toString());
                    extendinfo.setBroker_code(ua.getMemberuserid().toString());
                }
                if (StringUtils.isNotBlank(extendinfo.getBank_branch_name())) {
                    builder.setOpenBankName(extendinfo.getBank_branch_name());
                }

                String json = JSON.toJSONString(extendinfo);
                builder.setExtendInfo(json);
            }
            byte[] body = ProtoHelper.getNTAS(builder.build().toByteArray(),
                    FunCodeConstants.FunCode_Trade_t2bBankSignReq);
            rabbitTemplate.send(SysConstants.RabbitBankNtfKey, new Message(body, new MessageProperties()));
            log.info(builder.build().toString());
        } else {
            //解约
            BankMI1.t2bBankCancelSignReq.Builder builder = BankMI1.t2bBankCancelSignReq.newBuilder();
            BankAccountsign bankaccountsign = iBankAccountsignMapper.selectOne(new QueryWrapper<BankAccountsign>()
                    .eq("accountcode", sign.getAccountcode())
                    .eq("cusbankid", sign.getCusbankid()));
            Common.MessageHead.Builder hd = Common.MessageHead.newBuilder();
            hd.setUUID(uuid.toString());
            hd.setAccountID(Long.parseLong(sign.getAccountcode()));
            hd.setFunCode(FunCodeConstants.FunCode_Trade_t2bBankCancelSignReq);
            builder.setHeader(hd);
            builder.setTradeDate(DateTimeUtils.format(new Date(), DateTimeUtils.DATE_CHAR_PATTERN));
            builder.setExtOperatorID(uuid);
            String manageid = redisServiceUtil.getCacheMapValue(Constants.REDIS_HEADER_SYSPARAM, "001");
            builder.setExchId(manageid);
            builder.setAccountCode(bankaccountsign.getAccountcode());
            builder.setCusBankID(bankaccountsign.getCusbankid());
            builder.setIsForce(sign.getIsforce() == null ? 0 : sign.getIsforce());
            builder.setCurrency(bankaccountsign.getCurrency());
            builder.setBankChildAcc(bankaccountsign.getBankaccountno());
            builder.setBankChildAccName(bankaccountsign.getBankaccountname());

            byte[] body = ProtoHelper.getNTAS(builder.build().toByteArray(), FunCodeConstants.FunCode_Trade_t2bBankCancelSignReq);

            rabbitTemplate.send(SysConstants.RabbitBankNtfKey, new Message(body, new MessageProperties()));
        }

        synchronized (ca) {
            try {
                ca.wait(25000);
                Object rsp = ca.obj;
                if (rsp != null) {
                    switch (sign.getType()) {
                        case 0: {
                            BankMI1.t2bBankSignRsp rsp_ = (BankMI1.t2bBankSignRsp) rsp;
                            if (rsp_.getStatus() == 0) {
                                writelog(sign, 0, systemmanager);
                                if (sign.getOperatetype() != null && sign.getOperatetype() == 2) {
                                    return AjaxResult.success(Constants.Success_Code_Design, MessageType.MESSAGE_CODE_SYSTEM003.getCode(), request.getHeader("Accept-Language"), rsp_.getNetAddr());
                                } else {
                                    return AjaxResult.success(Constants.Success_Code_Design, MessageType.MESSAGE_CODE_SYSTEM004.getCode(), request.getHeader("Accept-Language"), rsp_.getNetAddr());
                                }
                            } else if (rsp_.getStatus() == 6007 || rsp_.getStatus() == 6001) {
                                return AjaxResult.success(rsp_.getStatus(), ProtoErrorCodes.resultMsg(rsp_.getStatus()), "", rsp_.getNetAddr());
                            } else {
                                return AjaxResult.error(Constants.Error_Code_Design, ProtoErrorCodes.resultMsg(rsp_.getStatus()) + ";" + rsp_.getCenterErrMsg(), "", rsp_.getNetAddr());
                            }
                        }
                        case 1: {
                            BankMI1.t2bBankCancelSignRsp rsp_ = (BankMI1.t2bBankCancelSignRsp) rsp;
                            if (rsp_.getStatus() == 0) {
                                writelog(sign, 1, systemmanager);
                                return AjaxResult.success(Constants.Success_Code_Design, MessageType.MESSAGE_CODE_SYSTEM005.getCode(), request.getHeader("Accept-Language"), rsp_.getNetAddr());
                            } else if (rsp_.getStatus() == 6007 || rsp_.getStatus() == 6001) {
                                return AjaxResult.success(rsp_.getStatus(), ProtoErrorCodes.resultMsg(rsp_.getStatus()), "", rsp_.getNetAddr());
                            } else {
                                return AjaxResult.error(Constants.Error_Code_Design, ProtoErrorCodes.resultMsg(rsp_.getStatus()) + ";" + rsp_.getCenterErrMsg(), "", rsp_.getNetAddr());
                            }
                        }
                        default:
                            break;
                    }

                } else {
                    return AjaxResult.error(Constants.Error_Code_Design, MessageType.MESSAGE_ERROR_CODE_SYSTEM005.getCode(), request.getHeader("Accept-Language"));
                }
            } catch (InterruptedException e) {
                log.error("处理银行签约信息失败，失败信息：" + Arrays.toString(e.getStackTrace()));
            } finally {
                SerialNumberUtils.lockMap.remove(uuid);
            }
        }
        return null;
    }

    @Override
    public AjaxResult<BankCusbankinfo> dealAccountSignInit(Long accountid, HttpServletRequest request) {
        Taaccount ta = iTaaccountMapper.selectOne(new QueryWrapper<Taaccount>().eq("accountid",accountid));
        Enumdicitem item = iEnumdicitemMapper.selectOne(new QueryWrapper<Enumdicitem>().eq("enumdiccode", "currency")
                .eq("enumitemname", Long.valueOf(ta.getCurrencyid())));

        // #6603 添加系统参数1016-是否强制配置使用银行渠道，若为1，则机构资料管理、会员子机构管理、经纪会员管理添加操作“银行渠道配置”
        // #6606 管理端】 机构\子机构登录》账号管理>资金账户管理》银行签约信息》新增\修改：根据系统参数1016-是否强制配置使用银行渠道，若为1，则查询机构\子机构配置的渠道
        String sp1016 = redisServiceUtil.getCacheMapValue(Constants.REDIS_HEADER_SYSPARAM, "1016");
        sp1016 = StringUtils.isBlank(sp1016) ? "0" : sp1016;
        List<BankCusbankinfo> cusBankList = null;
        if (sp1016.equals("1")){
            cusBankList = iBankAccountoutinapplyMapper.queryCusbanksForArea(ta.getUserid(),1);
        }else{
            cusBankList = iBankCusbankinfoMapper.selectList(new QueryWrapper<BankCusbankinfo>().
                    eq("currency", item.getBankmappedvalue()));
        }
        return AjaxResult.success(Constants.Success_Code_Design, MessageType.MESSAGE_CODE_SYSTEM001.getCode(), request.getHeader("Accept-Language"), cusBankList);
    }

    private void writelog(AccountSignParam sign, Integer type, Systemmanager user) {
        try {
            Systemmanagerlog syslog = new Systemmanagerlog();
            syslog.setUserid(user.getAutoid());
            syslog.setReletype(user.getReletype());
            syslog.setLogincode(user.getLogincode());
            syslog.setUsername(user.getUsername());
            syslog.setParentuserid(user.getAreauserid());
            syslog.setOperatetime(new Date());
            syslog.setIp(user.getLoginip());
            syslog.setResourcecode(SysConstants.BANK_SIGNORNOT);
            syslog.setResourcename("强制签解约");
            if (type == 0)
                syslog.setContent("签约accountcode=" + sign.getAccountcode());
            else
                syslog.setContent("解约accountcode=" + sign.getAccountcode());

            syslog.setOldvalue("");
            syslog.setNewvalue("");
            syslog.setRemark("");
            iSystemmanagerlogMapper.insert(syslog);
        } catch (Exception ex) {
            log.error("资金账户管理--> 银行签约模块报错。失败原因：" + Arrays.toString(ex.getStackTrace()));
        }
    }
}
