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.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.IDealLoginService;
import com.muchinfo.mtp3century.service.ISendMsgService;
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.mtp3century.utils.AjaxResult;
import com.muchinfo.mtp3common.vo.Calculator;
import com.muchinfo.mtp3common.vo.PageResult;
import com.muchinfo.mtp3common.vo.ProtoHelper;
import com.muchinfo.mtp3interface.mapper.*;
import com.muchinfo.mtp3pojos.entity.*;
import com.muchinfo.mtp3pojos.vo.ProtoErrorCodes;
import com.muchinfo.mtp3pojos.vo.investor.InvestorLoginQueryParam;
import com.muchinfo.mtp3pojos.vo.investor.InvestorLoginQueryResult;
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 org.springframework.transaction.annotation.Transactional;

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

@Service
public class DealLoginServiceImpl implements IDealLoginService {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    @Resource
    private IUserloginflowMapper iUserloginflowMapper;
    @Resource
    private SystemmanagerServiceImpl systemmanagerService;
    @Resource
    private IUserinfoMapper iUserinfoMapper;
    @Resource
    private ISendMsgService iSendMsgService;
    @Resource
    private ILoginaccountMapper iLoginaccountMapper;
    @Resource
    private ILogintaaccountMapper iLogintaaccountMapper;
    @Resource
    private RedisServiceUtil redisServiceUtil;
    @Resource
    private ISystemmanagerMapper iSystemmanagerMapper;
    @Resource
    private ICommonService iCommonService;
    @Resource
    private IUseraccountMapper iUseraccountMapper;
    @Resource
    private ISystemmanagerlogMapper iSystemmanagerlogMapper;
    @Resource
    private RabbitTemplate rabbitTemplate;
    @Resource
    private IUserauthinfoMapper iUserauthinfoMapper;


    @Override
    public PageResult<InvestorLoginQueryResult> queryInvestor(InvestorLoginQueryParam param, HttpServletRequest request) {
        param.setLoginusertype(1);
        IPage<InvestorLoginQueryResult> page = new Page<>(param.getPageNum(), param.getPageSize());
        IPage<InvestorLoginQueryResult> resultIPage = iLoginaccountMapper.queryLoginAccountPage(page, param);
        //返回列表
        PageResult<InvestorLoginQueryResult> 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 PageResult<Userloginflow> queryLoginLog(Long loginid, Integer pageNo, Integer pageSize, HttpServletRequest request) {
        IPage<Userloginflow> page = new Page<>(pageNo, pageSize);
        IPage<Userloginflow> resultPage = iUserloginflowMapper.selectPage(page, new QueryWrapper<Userloginflow>().eq("loginid", loginid));
        //返回列表
        PageResult<Userloginflow> pageResult = new PageResult<>();
        pageResult.setCode(Constants.Success_Code_Design);
        pageResult.setMessage(AjaxResult.dealMsg(MessageType.MESSAGE_CODE_SYSTEM001.getCode(), request.getHeader("Accept-Language")));
        pageResult.setPages(resultPage.getPages());
        pageResult.setCurrent(resultPage.getCurrent());
        pageResult.setTotal(resultPage.getTotal());
        pageResult.setPageSize(resultPage.getSize());
        pageResult.setData(resultPage.getRecords());
        return pageResult;
    }

    @Override
    public AjaxResult resetPwd(Long loginid, HttpServletRequest request) {
        Systemmanager systemmanager = iSystemmanagerMapper.selectOne(new QueryWrapper<Systemmanager>().eq("LOGINCODE", iCommonService.getUserLoginCode(request)));
        Loginaccount la = iLoginaccountMapper.selectOne(new QueryWrapper<Loginaccount>().eq("loginid", loginid));
        if (!checkLoginaccountRole(systemmanager, loginid)) {
            return AjaxResult.error(Constants.Error_Code_Design, MessageType.MESSAGE_ERROR_CODE_SYSTEM003.getCode(), request.getHeader("Accept-Language"));
        }
        dealPwd(loginid, redisServiceUtil.getCacheMapValue(Constants.REDIS_HEADER_SYSPARAM, "046"), systemmanager, la);
        //发送消息
        iCommonService.sendMsg(la, 2);
        return AjaxResult.success(Constants.Success_Code_Design, MessageType.MESSAGE_CODE_SYSTEM001.getCode(), request.getHeader("Accept-Language"));
    }

    @Override
    public AjaxResult lockAccount(Long loginid, Integer status, HttpServletRequest request) {
        Systemmanager systemmanager = iSystemmanagerMapper.selectOne(new QueryWrapper<Systemmanager>().eq("LOGINCODE", iCommonService.getUserLoginCode(request)));
        if (!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 (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());

            logger.debug("手工锁定：{}", 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_SYSTEM003.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) {
                    logger.error("处理账户状态失败，失败信息：" + e);
                } finally {
                    SerialNumberUtils.lockMap.remove(uuid);
                }
            }
        }
        return null;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult deleteAccount(Long loginid, HttpServletRequest request) {
        Systemmanager systemmanager = iSystemmanagerMapper.selectOne(new QueryWrapper<Systemmanager>().eq("LOGINCODE", iCommonService.getUserLoginCode(request)));
        if (!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(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);
        }

        //同时 删除三方账户
        List<Userauthinfo> userauthinfo = iUserauthinfoMapper.selectList(new QueryWrapper<Userauthinfo>().eq("loginid", loginid));
        userauthinfo.forEach(a -> {
            a.setIsvalid(0);
            iUserauthinfoMapper.update(a, new QueryWrapper<Userauthinfo>()
                    .eq("authid", a.getAuthid())
                    .eq("authtype", a.getAuthtype()));
        });

        // 删除”LoginTAAccount”表相关记录
        iLogintaaccountMapper.delete(new QueryWrapper<Logintaaccount>().eq("loginid", loginid));
        //发送消息
        iCommonService.sendMsg(la, 1);
        return AjaxResult.success(Constants.Success_Code_Design, MessageType.MESSAGE_CODE_SYSTEM001.getCode(), request.getHeader("Accept-Language"));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult restoreAccount(Long loginid, HttpServletRequest request) {
        Systemmanager systemmanager = iSystemmanagerMapper.selectOne(new QueryWrapper<Systemmanager>().eq("LOGINCODE", iCommonService.getUserLoginCode(request)));
        if (!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);
        }

        Userinfo ui = iUserinfoMapper.selectOne(new QueryWrapper<Userinfo>().eq("userid", la.getUserid()));
        if (ui != null && StringUtils.isNotBlank(ui.getMobile())) {
            Map<String, Object> properties = new HashMap<String, Object>();
            // 查询手机号是否已被绑定，如果没有则添加记录
            properties.put("authtype", 3);// 3:手机号
            properties.put("authid", ui.getMobile());
            Userauthinfo userAuthInfo = iUserauthinfoMapper.selectOne(new QueryWrapper<Userauthinfo>()
                    .eq("authtype", 3)
                    .eq("authid", ui.getMobile())
            );
            if (Objects.isNull(userAuthInfo)) {
                Userauthinfo newObj = new Userauthinfo();
                newObj.setAuthid(ui.getMobile());
                newObj.setAuthtype(3);
                newObj.setLoginid(loginid);
                newObj.setUserid(la.getUserid());
                newObj.setIsvalid(1);
                iUserauthinfoMapper.insert(newObj);
            }
        }
        return AjaxResult.success(Constants.Success_Code_Design, MessageType.MESSAGE_CODE_SYSTEM001.getCode(), request.getHeader("Accept-Language"));
    }

    @Override
    public AjaxResult<Userauthinfo> queryUserAuthInfo(Long loginid, HttpServletRequest request) {
        Systemmanager systemmanager = iSystemmanagerMapper.selectOne(new QueryWrapper<Systemmanager>().eq("LOGINCODE", iCommonService.getUserLoginCode(request)));
        Userauthinfo userAuthInfo = iUserauthinfoMapper.selectOne(new QueryWrapper<Userauthinfo>()
                .eq("authtype", 3)
                .eq("loginid", loginid)
        );
        Long userId;

        if (Objects.nonNull(userAuthInfo)) {
            userId = userAuthInfo.getUserid();
            Useraccount useraccount = iUseraccountMapper.selectOne(new QueryWrapper<Useraccount>().eq("userid", userAuthInfo.getUserid()));
            userAuthInfo.setBindname(useraccount.getAccountname());
        } else {
            Userauthinfo newUser = new Userauthinfo();
            Loginaccount la = iLoginaccountMapper.selectOne(new QueryWrapper<Loginaccount>().eq("loginid", loginid));
            Useraccount useraccount = iUseraccountMapper.selectOne(new QueryWrapper<Useraccount>().eq("userid", la.getUserid()));
            userId = useraccount.getUserid();
            newUser.setBindname(useraccount.getAccountname());
            userAuthInfo = newUser;
        }

        String sysParam = iCommonService.getSysparmById(SysConstants.SYSPARAM_CODE_OPEN_TYPE);
        userAuthInfo.setOpentype(sysParam != null ? sysParam : "0");
        //记录日志
        systemmanagerService.saveMGLog(systemmanager, SysConstants.PART_INVESTOR_MANAGE, userId);
        return AjaxResult.success(Constants.Success_Code_Design, MessageType.MESSAGE_CODE_SYSTEM001.getCode(), request.getHeader("Accept-Language"), userAuthInfo);
    }


    private void dealPwd(Long accountid, String password, Systemmanager user, Loginaccount la) {

        if (la != null) {
            la.setHasupdatedpwd(0);
            la.setPassword(EncryptionUtils.encryptSHA(la.getLoginid() + password));
            la.setModifierid(user.getAutoid());
            la.setModifytime(new Date());

            iLoginaccountMapper.update(la, new QueryWrapper<Loginaccount>().eq("loginid", la.getLoginid()));
            writelog(la, user, SysConstants.BUTTON_CODE_RESET);
        }

        //重置密码短信消息
        assert la != null;
        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(accountid.toString());
            strs.add("登录");
            strs.add(password);
            //尊敬的{accountname}，根据您的申请，您的交易账号{accountid}{type}密码已经重置为:{password};请及时登录系统修改您的相关密码,并注意妥善保管。
            iSendMsgService.sendSMSConnetion(23, EncryptionUtils.decryptForAES(ui.getMobile()), strs);
        }
    }

    private boolean checkLoginaccountRole(Systemmanager systemmanager, Long loginid) {
        //平台
        if (systemmanager.getReletype() == 1) {
            return true;
        }

        //会员或子机构
        if (systemmanager.getReletype() == 2 || systemmanager.getReletype() == 3) {
            Loginaccount la = iLoginaccountMapper.selectOne(new QueryWrapper<Loginaccount>().eq("loginid", loginid));
            if (la == null)
                return false;
            Useraccount ua = iUseraccountMapper.selectOne(new QueryWrapper<Useraccount>().eq("userid", la.getUserid()));
            if (ua == null)
                return false;
            if (ua.getSubarealevelpath().contains("," + systemmanager.getAreauserid().toString() + ",")) {
                return true;
            }
        }
        return false;
    }

    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);
                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.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) {
            logger.warn(e.getMessage());
        }
    }
}
