package com.muchinfo.mtp3century.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.muchinfo.mtp.proto.Common;
import com.muchinfo.mtp.proto.SystemMI1;
import com.muchinfo.mtp3century.service.ICommonService;
import com.muchinfo.mtp3century.service.ITradingAccountService;
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.CommonUtil;
import com.muchinfo.mtp3common.utils.EncryptionUtils;
import com.muchinfo.mtp3common.utils.SerialNumberUtils;
import com.muchinfo.mtp3common.vo.ProtoHelper;
import com.muchinfo.mtp3century.utils.AjaxResult;
import com.muchinfo.mtp3common.vo.Calculator;
import com.muchinfo.mtp3common.vo.PageResult;
import com.muchinfo.mtp3interface.mapper.*;
import com.muchinfo.mtp3pojos.entity.*;
import com.muchinfo.mtp3pojos.vo.ProtoErrorCodes;
import com.muchinfo.mtp3pojos.vo.tradingacc.InitAddResult;
import com.muchinfo.mtp3pojos.vo.tradingacc.TradingAccountAddParam;
import com.muchinfo.mtp3pojos.vo.tradingacc.TradingAccountQueryParam;
import com.muchinfo.mtp3pojos.vo.tradingacc.TradingAccountQueryResult;
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.stereotype.Service;

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

@Service
public class TradingAccountServiceImpl implements ITradingAccountService {

    private final Logger log = LoggerFactory.getLogger(this.getClass());

    @Resource
    private ICommonService iCommonService;
    @Resource
    private ISystemmanagerMapper iSystemmanagerMapper;
    @Resource
    private ISystemmanagerlogMapper iSystemmanagerlogMapper;
    @Resource
    private ILoginaccountMapper iLoginaccountMapper;
    @Resource
    private ILogintaaccountMapper iLogintaaccountMapper;
    @Resource
    private ITaaccountMapper iTaaccountMapper;
    @Resource
    private IUserinfoMapper iUserinfoMapper;
    @Resource
    private SendMsgServiceImpl sendMsgService;
    @Resource
    private IFuncmenulistMapper iFuncmenulistMapper;
    @Resource
    private RabbitTemplate rabbitTemplate;
    @Resource
    private SystemmanagerServiceImpl systemmanagerService;
    @Resource
    private IUserauthinfoMapper iUserauthinfoMapper;

    @Override
    public PageResult<TradingAccountQueryResult> query(HttpServletRequest request, TradingAccountQueryParam param) {
        Systemmanager systemmanager = iSystemmanagerMapper.selectOne(new QueryWrapper<Systemmanager>().eq("LOGINCODE", iCommonService.getUserLoginCode(request)));
        param.setUserid(systemmanager.getAreauserid());
        param.setLoginusertype(2);
        IPage<TradingAccountQueryResult> page = new Page<>(param.getPageNum(), param.getPageSize());
        IPage<TradingAccountQueryResult> userAccountVos = iLoginaccountMapper.queryTradingAccount(page, param);
        PageResult<TradingAccountQueryResult> pageResult = new PageResult<>();
        pageResult.setCode(Constants.Success_Code_Design);
        pageResult.setMessage(AjaxResult.dealMsg(MessageType.MESSAGE_CODE_SYSTEM001.getCode(), request.getHeader("Accept-Language")));
        pageResult.setPages(userAccountVos.getPages());
        pageResult.setCurrent(userAccountVos.getCurrent());
        pageResult.setTotal(userAccountVos.getTotal());
        pageResult.setPageSize(userAccountVos.getSize());
        pageResult.setData(userAccountVos.getRecords());
        return pageResult;
    }

    @Override
    public AjaxResult<Loginaccount> view(HttpServletRequest request, Long loginid) {
        Loginaccount loginaccount = iLoginaccountMapper.selectOne(new QueryWrapper<Loginaccount>().eq("loginid", loginid));
        List<Logintaaccount> list = iLogintaaccountMapper.selectList(new QueryWrapper<Logintaaccount>().eq("loginid", loginid));
        if (CollectionUtils.isEmpty(list)) {
            List<Taaccount> tas = iTaaccountMapper.selectList(new QueryWrapper<Taaccount>().eq("userid", loginaccount.getUserid()));
            List<Long> ids = tas.stream().map(Taaccount::getAccountid).collect(Collectors.toList());
            loginaccount.setAccountIdS(ids);
        } else {
            List<Long> ids = list.stream().map(Logintaaccount::getAccountid).collect(Collectors.toList());
            loginaccount.setAccountIdS(ids);
        }
        return AjaxResult.success(Constants.Success_Code_Design, MessageType.MESSAGE_CODE_SYSTEM001.getCode(), request.getHeader("Accept-Language"), loginaccount);
    }

    @Override
    public AjaxResult resetPwd(HttpServletRequest request, Long loginid) {
        Systemmanager systemmanager = iSystemmanagerMapper.selectOne(new QueryWrapper<Systemmanager>().eq("LOGINCODE", iCommonService.getUserLoginCode(request)));
        if (!iCommonService.checkLoginAccountRole(systemmanager, loginid)) {
            return AjaxResult.error(Constants.Error_Code_Design, MessageType.MESSAGE_ERROR_CODE_SYSTEM003.getCode(), request.getHeader("Accept-Language"));
        }
        String password = iCommonService.getSystemParam(Constants.REDIS_HEADER_SYSPARAM, "046");
        Loginaccount la = iLoginaccountMapper.selectOne(new QueryWrapper<Loginaccount>().eq("loginid", loginid));
        if (la != null) {
            la.setHasupdatedpwd(0);
            la.setPassword(EncryptionUtils.encryptSHA(la.getLoginid() + password));
            la.setModifierid(systemmanager.getAutoid());
            la.setModifytime(new Date());

            iLoginaccountMapper.update(la, new QueryWrapper<Loginaccount>().eq("LOGINID", la.getLoginid()));
            writelog(la, systemmanager, SysConstants.BUTTON_CODE_RESET);

            //重置密码短信消息
            Userinfo ui = iUserinfoMapper.selectOne(new QueryWrapper<Userinfo>().eq("userid", la.getUserid()));
            if (StringUtils.isNotBlank(ui.getMobile())) {
                List<String> strs = new ArrayList<String>();
                strs.add(ui.getCustomername());
                strs.add(loginid.toString());
                strs.add("登录");
                strs.add(password);
                //尊敬的{accountname}，根据您的申请，您的交易账号{accountid}{type}密码已经重置为:{password};请及时登录系统修改您的相关密码,并注意妥善保管。
                sendMsgService.sendSMSConnetion(23, EncryptionUtils.decryptForAES(ui.getMobile()), strs);
            }
        }
        return AjaxResult.success(Constants.Success_Code_Design, MessageType.MESSAGE_CODE_SYSTEM001.getCode(), request.getHeader("Accept-Language"));
    }

    @Override
    public AjaxResult lockAccount(HttpServletRequest request, Integer status, Long loginid) {
        Systemmanager systemmanager = iSystemmanagerMapper.selectOne(new QueryWrapper<Systemmanager>().eq("LOGINCODE", iCommonService.getUserLoginCode(request)));
        Loginaccount la = iLoginaccountMapper.selectOne(new QueryWrapper<Loginaccount>().eq("loginid", loginid));
        if (la != null) {
            // 发送消息 解锁 ,回应
            Long uuid = SerialNumberUtils.getNewSerialNumber(SerialNumberUtils.prefix_account);

            SystemMI1.LoginStatusOperReq.Builder builder = SystemMI1.LoginStatusOperReq.newBuilder();
            Common.MessageHead.Builder hd = Common.MessageHead.newBuilder();
            hd.setUUID(uuid.toString());
            hd.setClientTime(System.currentTimeMillis());
            hd.setResponseTopic(SysConstants.RabbitUserNtfKey);
            hd.setFunCode(FunCodeConstants.FunCode_LoginStatusOperReq);
            builder.setHeader(hd);
            builder.setLoginID(loginid);
            builder.setLoginStatus(status);
            builder.setOperatorID(systemmanager.getAutoid().intValue());

            log.info("手工锁定：{}", builder.build().toString());
            byte[] body = ProtoHelper.getNTAS(builder.build().toByteArray(),
                    FunCodeConstants.FunCode_LoginStatusOperReq);

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

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

            if (status == 1) {
                systemmanagerService.writeOperateLog(SysConstants.PART_INVESTOR_MANAGE, String.format("解锁登录账户(loginid=%s)成功", loginid), systemmanager, null, null, null);
            } else if (status == 2) {
                systemmanagerService.writeOperateLog(SysConstants.PART_INVESTOR_MANAGE, String.format("锁定登录账户(loginid=%s)成功", loginid), systemmanager, null, null, null);
            }

            synchronized (ca) {
                try {
                    ca.wait(10000);
                    Object rsp = ca.obj;
                    if (rsp != null) {
                        SystemMI1.LoginStatusOperRsp rsp_ = (SystemMI1.LoginStatusOperRsp) rsp;
                        if (rsp_.getRetCode() == 0) {
                            return AjaxResult.success(Constants.Success_Code_Design, MessageType.MESSAGE_CODE_SYSTEM008.getCode(), request.getHeader("Accept-Language"));
                        } else {
                            return AjaxResult.error(Constants.Error_Code_Design, ProtoErrorCodes.resultMsg(rsp_.getRetCode()), "");
                        }
                    } else {
                        return AjaxResult.error(Constants.Error_Code_Design, MessageType.MESSAGE_ERROR_CODE_SYSTEM006.getCode(), request.getHeader("Accept-Language"));
                    }
                } catch (InterruptedException e) {
                    log.error("收取锁定交易账号通知失败，失败原因：" + e.getMessage());
                } finally {
                    SerialNumberUtils.lockMap.remove(uuid);
                }
            }
        }
        return null;
    }

    @Override
    public AjaxResult delAccount(HttpServletRequest request, Long loginid) {
        Systemmanager systemmanager = iSystemmanagerMapper.selectOne(new QueryWrapper<Systemmanager>().eq("LOGINCODE", iCommonService.getUserLoginCode(request)));
        if (!iCommonService.checkLoginAccountRole(systemmanager, loginid)) {
            return AjaxResult.error(Constants.Error_Code_Design, MessageType.MESSAGE_ERROR_CODE_SYSTEM003.getCode(), request.getHeader("Accept-Language"));
        }

        //同时 删除三方账户
        Userauthinfo userauthinfo = iUserauthinfoMapper.selectOne(new QueryWrapper<Userauthinfo>().eq("loginid", loginid));
        if (Objects.nonNull(userauthinfo)) {
            userauthinfo.setIsvalid(0);
            iUserauthinfoMapper.update(userauthinfo, new QueryWrapper<Userauthinfo>().eq("loginid", loginid));
        }
        // 删除”LoginTAAccount”表相关记录
        iLogintaaccountMapper.delete(new QueryWrapper<Logintaaccount>().eq("loginid", loginid));

        Loginaccount la = iLoginaccountMapper.selectOne(new QueryWrapper<Loginaccount>().eq("loginid", loginid));
        if (Objects.nonNull(la)) {
            la.setLoginstatus(3);
            la.setModifierid(systemmanager.getAutoid());
            la.setModifytime(new Date());
            iLoginaccountMapper.update(la, new QueryWrapper<Loginaccount>().eq("loginid", la.getLoginid()));

            writelog(la, systemmanager, SysConstants.BUTTON_CODE_DEL);

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

    @Override
    public AjaxResult undelAccount(HttpServletRequest request, Long loginid) {
        Systemmanager systemmanager = iSystemmanagerMapper.selectOne(new QueryWrapper<Systemmanager>().eq("LOGINCODE", iCommonService.getUserLoginCode(request)));
        if (!iCommonService.checkLoginAccountRole(systemmanager, loginid)) {
            return AjaxResult.error(Constants.Error_Code_Design, MessageType.MESSAGE_ERROR_CODE_SYSTEM003.getCode(), request.getHeader("Accept-Language"));
        }
        Loginaccount la = iLoginaccountMapper.selectOne(new QueryWrapper<Loginaccount>().eq("loginid", loginid));
        if (Objects.nonNull(la)) {
            la.setLoginstatus(1);
            la.setModifierid(systemmanager.getAutoid());
            la.setModifytime(new Date());
            iLoginaccountMapper.update(la, new QueryWrapper<Loginaccount>().eq("loginid", la.getLoginid()));

            writelog(la, systemmanager, SysConstants.BUTTON_CODE_ACTIVE);

            iCommonService.sendMsg(la, 0);
        }

        //同时 恢复手机号登录 20240417
        bindUserMobielToLoginID(la.getUserid(), la.getLoginid());
        //同时 恢复三方账户
        Userauthinfo userauthinfo = iUserauthinfoMapper.selectOne(new QueryWrapper<Userauthinfo>().eq("loginid", loginid));
        if (Objects.nonNull(userauthinfo)) {
            userauthinfo.setIsvalid(1);
            iUserauthinfoMapper.update(userauthinfo, new QueryWrapper<Userauthinfo>().eq("loginid", loginid));
        }

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

    @Override
    public AjaxResult add(HttpServletRequest request, TradingAccountAddParam param) {
        Loginaccount current = iLoginaccountMapper.selectOne(new QueryWrapper<Loginaccount>().eq("loginid", param.getLoginid()));
        if (Objects.nonNull(current)) {
            return AjaxResult.error(Constants.Error_Code_Design, MessageType.TRAACC_ERROR_CODE_001.getCode(), request.getHeader("Accept-Language"));
        }
        Systemmanager systemmanager = iSystemmanagerMapper.selectOne(new QueryWrapper<Systemmanager>().eq("LOGINCODE", iCommonService.getUserLoginCode(request)));
        Loginaccount la = new Loginaccount();
        la.setLoginfailnum(0);
        la.setLoginid(param.getLoginid());
        la.setLoginstatus(1);
        la.setLoginusertype(param.getLoginusertype());
        la.setPassword(EncryptionUtils.encryptSHA(la.getLoginid() + param.getPassword()));
        la.setUserid(systemmanager.getAreauserid());
        la.setModifierid(systemmanager.getAutoid());
        la.setModifytime(new Date());
        la.setHasupdatedpwd(0);
        iLoginaccountMapper.insert(la);

        if (StringUtils.isNotEmpty(param.getAccountids())) {
            List<Long> accountids = Arrays.stream(param.getAccountids().split(","))
                    .map(Long::valueOf)
                    .collect(Collectors.toList());

            for (Long id : accountids) {
                Logintaaccount lt = new Logintaaccount();
                lt.setAccountid(id);
                lt.setLoginid(la.getLoginid());
                lt.setModifierid(systemmanager.getAutoid());
                lt.setModifytime(new Date());
                iLogintaaccountMapper.insert(lt);
            }
        }
        writelog(la, systemmanager, SysConstants.BUTTON_CODE_ADD);
        return AjaxResult.success(Constants.Success_Code_Design, MessageType.MESSAGE_CODE_SYSTEM001.getCode(), request.getHeader("Accept-Language"));
    }

    @Override
    public AjaxResult<InitAddResult> initAdd(HttpServletRequest request) {
        Systemmanager systemmanager = iSystemmanagerMapper.selectOne(new QueryWrapper<Systemmanager>().eq("LOGINCODE", iCommonService.getUserLoginCode(request)));
        InitAddResult result = new InitAddResult();
        List<Taaccount> list = iTaaccountMapper.selectList(new QueryWrapper<Taaccount>()
                .eq("tradestatus", 1)
                .and(a -> a.eq("userid", systemmanager.getAreauserid()).or().eq("relateduserid", systemmanager.getAreauserid())));
        result.setTaaccounts(list);
        result.setLoginid(getNewLoginIdByUserid(systemmanager.getAreauserid(), 2));
        return AjaxResult.success(Constants.Success_Code_Design, MessageType.MESSAGE_CODE_SYSTEM001.getCode(), request.getHeader("Accept-Language"), result);
    }

    @Override
    public AjaxResult edit(HttpServletRequest request, TradingAccountAddParam vo) {
        Systemmanager systemmanager = iSystemmanagerMapper.selectOne(new QueryWrapper<Systemmanager>().eq("LOGINCODE", iCommonService.getUserLoginCode(request)));

        iLogintaaccountMapper.delete(new QueryWrapper<Logintaaccount>().eq("loginid", vo.getLoginid()));

        if (StringUtils.isNotEmpty(vo.getAccountids())) {
            List<Long> accountids = Arrays.stream(vo.getAccountids().split(","))
                    .map(Long::valueOf)
                    .collect(Collectors.toList());

            for (Long id : accountids) {
                Logintaaccount lt = new Logintaaccount();
                lt.setAccountid(id);
                lt.setLoginid(vo.getLoginid());
                lt.setModifierid(systemmanager.getAutoid());
                lt.setModifytime(new Date());
                iLogintaaccountMapper.insert(lt);
            }
        }
        Loginaccount la = new Loginaccount();
        la.setLoginid(vo.getLoginid());
        sendMsg(la, 4);

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

    private void sendMsg(Loginaccount la, Integer type) {
        Set<Long> logins = new HashSet<>();
        logins.add(la.getLoginid());

        // 0 新增帐号 1 删除帐号  2 修改帐号 3 修改帐号个性化 4 修改账户权限 5 删除三方登陆信息
        Thread myThread = new Thread(new Runnable() {
            public void run() {
                try {
                    // 使用线程发送消息  延迟5秒发送, 避免数据库未写入
                    Thread.sleep(5000);

                    sendMsgService.sendLoginMsg(logins, type, 0);
                } catch (Exception ex) {
                    log.error("发送消息失败，失败原因：" + ex);
                }
            }
        });

        // 启动线程
        myThread.start();
    }


    public Long getNewLoginIdByUserid(Long userid, int type) {
        if (type == 1) {
            //投资者
            //生成投资者时会初始化一个登录账户 后面的直接 +1
            Long userid_ = iLoginaccountMapper.selectOne(new QueryWrapper<Loginaccount>()
                    .eq("userid", userid)
                    .select("loginid").orderByDesc("loginid").
                    last("limit 1")).getLoginid();
            if (userid_.toString().length() == 14) {
                return Long.valueOf(userid_ + "01");
            }
            return userid_ + 1;
        } else {
            //机构
            Map<String, Object> map = new HashMap<>();
            map.put("userid", userid);
            map.put("loginusertype", 2);
            Long count = iLoginaccountMapper.selectCount(new QueryWrapper<Loginaccount>()
                    .eq("userid", userid)
                    .eq("loginusertype", 2)
            );
            return Long.valueOf("1" + userid.toString() + CommonUtil.addZero(String.valueOf((count + 1)), 7));
        }
    }

    private void writelog(Loginaccount la, Systemmanager opeartion, String button_code) {
        try {
            Systemmanagerlog log = new Systemmanagerlog();
            log.setUserid(opeartion.getAutoid());
            log.setReletype(opeartion.getReletype());
            log.setLogincode(opeartion.getLogincode());
            log.setUsername(opeartion.getUsername());
            log.setParentuserid(opeartion.getAreauserid());
            log.setOperatetime(new Date());
            log.setIp(opeartion.getLoginip());
            if (la.getLoginusertype() == 1) {
                log.setResourcecode(SysConstants.PART_INVESTOR_MANAGE);
                Funcmenulist menu = iFuncmenulistMapper.selectOne(new QueryWrapper<Funcmenulist>().eq("RESOURCECODE", SysConstants.PART_INVESTOR_MANAGE));
                if (menu != null)
                    log.setResourcename(menu.getResourcename());
                else
                    log.setResourcename("交易商管理");
                if (button_code.equals(SysConstants.BUTTON_CODE_DEL))
                    log.setContent("注销交易商登录账户(loginid=" + la.getLoginid() + ")成功");
                if (button_code.equals(SysConstants.BUTTON_CODE_ACTIVE))
                    log.setContent("恢复交易商登录账户(loginid=" + la.getLoginid() + ")成功");
                if (button_code.equals(SysConstants.BUTTON_CODE_ADD))
                    log.setContent("新增交易商登录账户(loginid=" + la.getLoginid() + ")成功");
                if (button_code.equals(SysConstants.BUTTON_CODE_RESET))
                    log.setContent("重置交易商登录账户(loginid=" + la.getLoginid() + ")密码成功");
            } else {
                log.setResourcecode(SysConstants.OPERATION_LOGIN);
                Funcmenulist menu = iFuncmenulistMapper.selectOne(new QueryWrapper<Funcmenulist>().eq("RESOURCECODE", SysConstants.PART_INVESTOR_MANAGE));
                if (menu != null)
                    log.setResourcename(menu.getResourcename());
                else
                    log.setResourcename("自营登录账户管理");
                if (button_code.equals(SysConstants.BUTTON_CODE_DEL))
                    log.setContent("注销自营登录账户(loginid=" + la.getLoginid() + ")成功");
                if (button_code.equals(SysConstants.BUTTON_CODE_ACTIVE))
                    log.setContent("恢复自营登录账户(loginid=" + la.getLoginid() + ")成功");
                if (button_code.equals(SysConstants.BUTTON_CODE_ADD))
                    log.setContent("新增自营登录账户(loginid=" + la.getLoginid() + ")成功");
                if (button_code.equals(SysConstants.BUTTON_CODE_RESET))
                    log.setContent("重置自营登录账户(loginid=" + la.getLoginid() + ")密码成功");
            }
            log.setOldvalue("");
            log.setNewvalue("");
            iSystemmanagerlogMapper.insert(log);
        } catch (Exception e) {
            log.error("插入操作日志失败，失败原因：" + e.getMessage());
        }
    }

    public void bindUserMobielToLoginID(Long userID, Long loginID) {
        Userinfo ui = iUserinfoMapper.selectOne(new QueryWrapper<Userinfo>().eq("userid", userID));
        if (Objects.nonNull(ui) && StringUtils.isNotBlank(ui.getMobile())) {
            Userauthinfo userAuthInfo = iUserauthinfoMapper.selectOne(new QueryWrapper<Userauthinfo>()
                    .eq("authtype", 3)
                    .eq("authid", ui.getMobile()));
            if (userAuthInfo == null) {
                Userauthinfo newObj = new Userauthinfo();
                newObj.setAuthid(ui.getMobile());
                newObj.setAuthtype(3);
                newObj.setLoginid(loginID);
                newObj.setUserid(userID);
                newObj.setIsvalid(1);
                iUserauthinfoMapper.insert(newObj);
            }
        }
    }
}
