package com.jeequan.jeepay.mgr.ctrl.agent;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.DesensitizedUtil;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jeequan.jeepay.bizcommons.manage.sms.SmsManager;
import com.jeequan.jeepay.components.mq.model.CleanAgentLoginAuthCacheMQ;
import com.jeequan.jeepay.components.mq.model.ResetIsvMchAppInfoConfigMQ;
import com.jeequan.jeepay.components.mq.vender.IMQSender;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.SysUser;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.model.smsconfig.SmsBizDiyContentModel;
import com.jeequan.jeepay.db.entity.AgentInfo;
import com.jeequan.jeepay.db.entity.InfoAccount;
import com.jeequan.jeepay.db.entity.MchInfo;
import com.jeequan.jeepay.db.entity.SysUserEntity;
import com.jeequan.jeepay.mgr.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.InfoAccountService;
import com.jeequan.jeepay.service.impl.SysUserAuthService;
import com.jeequan.jeepay.service.impl.SysUserService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.util.*;

/***
 * 服务商管理
 *
 * @author terrfly
 *
 * @date 2022/3/15 15:25
 */
@RestController
@RequestMapping("/api/agents")
public class AgentInfoController extends CommonCtrl {

    @Autowired
    private SysUserAuthService sysUserAuthService;
    @Autowired
    private InfoAccountService infoAccountService;
    @Autowired
    private IMQSender mqSender;
    @Autowired
    private SmsManager smsManager;
    @Autowired
    private SysUserService sysUserService;

    @PreAuthorize("hasAuthority('ENT_AGENT_LIST')")
    @RequestMapping(value = "", method = RequestMethod.GET)
    public ApiRes list() {
        AgentInfo agentInfo = getObject(AgentInfo.class);

        LambdaQueryWrapper<AgentInfo> wrapper = AgentInfo.gw();

        selectParams(agentInfo, wrapper);
        wrapper.orderByDesc(AgentInfo::getCreatedAt);

        // 余额查询条件大于该余额服务商
        Long balanceAmount = getAmountL("balanceAmount");
        if (balanceAmount != null) {
            wrapper.exists("select tia.* from t_info_account tia where tia.balance_amount >= " + balanceAmount + " and tia.info_id = t_agent_info.agent_no");
        }

        IPage<AgentInfo> pages = agentInfoService.page(getIPage(true), wrapper);

        Map<Long, AgentInfo> agentInfoMap = new HashMap<>();
        List<Long> agentUidList = new ArrayList<>();
        // 统计服务商下商户数量
        for (AgentInfo info : pages.getRecords()) {
            agentInfoMap.put(info.getInitUserId(), info);

            // 数据脱敏
            info.setContactTel(DesensitizedUtil.mobilePhone(info.getContactTel()));

            long count = 0;
            if (StringUtils.isEmpty(info.getPid())) {
                count = mchInfoService.count(MchInfo.gw().and(i -> {
                    i.eq(MchInfo::getAgentNo, info.getAgentNo())
                            .or().eq(MchInfo::getTopAgentNo, info.getAgentNo());
                }));
            } else {
                count = mchInfoService.count(MchInfo.gw().eq(MchInfo::getTopAgentNo, info.getPid()));
            }
            info.addExt("mchCount", count);


            InfoAccount infoAccount = infoAccountService.queryAgentAccount(info.getAgentNo());

            info.addExt("balanceAmount", infoAccount == null ? null : infoAccount.getBalanceAmount());
            info.addExt("unAmount", infoAccount == null ? null : infoAccount.getUnAmount());
            info.addExt("auditProfitAmount", infoAccount == null ? null : infoAccount.getAuditProfitAmount());

            agentUidList.add(info.getInitUserId());
        }

        sysUserService.lambdaQuery()
                .in(!CollUtil.isEmpty(agentUidList),SysUserEntity::getSysUserId, agentUidList)
                .list().forEach(item -> {
                    Optional.ofNullable(agentInfoMap.get(item.getSysUserId()))
                            .ifPresent(agentItem -> {
                                agentItem.setInviteCode(item.getInviteCode());
                            });
                });
        return ApiRes.page(pages);
    }

    @PreAuthorize("hasAuthority('ENT_AGENT_INFO_ADD')")
    @MethodLog(remark = "新增服务商")
    @PostMapping
    public ApiRes add() {
        AgentInfo agentInfo = getObject(AgentInfo.class);
        Byte isNotify = getValByteRequired("isNotify");
        // 获取传入的服务商登录名、登录密码
        String loginPassword = getValString("loginPassword");
        if (StringUtils.isBlank(loginPassword)) {
            loginPassword = null;
        }
        agentInfo.setAgentNo("P" + DateUtil.format(new Date(), "yyMMdd") + RandomUtil.randomNumbers(6));
        // 当前登录用户信息
        SysUser sysUser = getCurrentUser().getSysUser();
        agentInfo.setCreatedUid(sysUser.getSysUserId());
        agentInfo.setCreatedBy(sysUser.getRealname());

        agentInfoService.addAgentV2(agentInfo, loginPassword, false);

        // 发送短信通知
        if (isNotify == CS.YES) {
            smsManager.sendDiyContentSms(SmsBizDiyContentModel.genUserOpenAccount(agentInfo.getContactTel(), agentInfo.getLoginUsername(), loginPassword));
        }

        return ApiRes.ok();
    }

    @PreAuthorize("hasAuthority('ENT_AGENT_INFO_DEL')")
    @MethodLog(remark = "删除服务商")
    @DeleteMapping(value = "/{agentNo}")
    public ApiRes delete(@PathVariable("agentNo") String agentNo) {

        List<Long> userIdList = agentInfoService.removeByAgentNo(agentNo);
        // 推送mq删除redis用户缓存
        mqSender.send(CleanAgentLoginAuthCacheMQ.build(userIdList));

        return ApiRes.ok();
    }

    @PreAuthorize("hasAuthority('ENT_AGENT_INFO_EDIT')")
    @MethodLog(remark = "更新服务商信息")
    @PutMapping(value = "/{agentNo}")
    public ApiRes update(@PathVariable("agentNo") String agentNo) {

        //获取查询条件
        AgentInfo agentInfo = getObject(AgentInfo.class);
        agentInfo.setAgentNo(agentNo); //设置服务商号主键

        agentInfo.setIsvNo(null); // 不允许更改
        agentInfo.setLoginUsername(null); // 防止修改用户登录名

        boolean resetPass = getReqParamJSON().getBooleanValue("resetPass");
        String confirmPwd = null;
        if (resetPass) {
            confirmPwd = Boolean.TRUE.equals(getReqParamJSON().getBoolean("defaultPass")) ? null : Base64.decodeStr(getValStringRequired("confirmPwd"));
        }

        // 更新 & 得到需要删除的用户ID的记录
        Set<Long> removeCacheUserIdList = agentInfoService.updateAgent(agentInfo, getReqParamJSON(), resetPass, confirmPwd);

        // 推送mq删除redis用户认证信息
        if (!removeCacheUserIdList.isEmpty()) {
            mqSender.send(CleanAgentLoginAuthCacheMQ.build(new ArrayList<>(removeCacheUserIdList)));
        }

        // 推送mq到目前节点进行更新数据
        mqSender.send(ResetIsvMchAppInfoConfigMQ.build(ResetIsvMchAppInfoConfigMQ.RESET_TYPE_MCH_INFO, null, agentNo, null));

        return ApiRes.ok();
    }

    @PreAuthorize("hasAnyAuthority('ENT_AGENT_INFO_VIEW', 'ENT_AGENT_INFO_EDIT')")
    @RequestMapping(value = "/{agentNo}", method = RequestMethod.GET)
    public ApiRes detail(@PathVariable("agentNo") String agentNo) {
        AgentInfo agentInfo = agentInfoService.getById(agentNo);
        if (agentInfo == null) {
            return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_SEARCH);
        }

        // 服务商钱包信息
        InfoAccount account = infoAccountService.queryAgentAccount(agentNo);
        if (account != null) {
            agentInfo.addExt("balanceAmount", account.getBalanceAmount());
            agentInfo.addExt("unAmount", account.getUnAmount());
            agentInfo.addExt("auditProfitAmount", account.getAuditProfitAmount());
        }

        return ApiRes.ok(agentInfo);
    }


    @PreAuthorize("hasAuthority('ENT_AGENT_BALANCE_CHANGE')")
    @MethodLog(remark = "服务商调账")
    @RequestMapping(value = "/balanceAmounts/{agentNo}", method = RequestMethod.POST)
    public ApiRes balanceAmounts(@PathVariable("agentNo") String agentNo) {

        String currentPassword = Base64.decodeStr(getValStringRequired("currentPassword"));

        Long changeAmount = getRequiredAmountL("changeAmount");
        // 备注
        String remark = getValString("remark");

        //验证当前密码是否正确
        if (!sysUserAuthService.validateCurrentUserPwd(currentPassword)) {
            throw new BizException("密码验证失败！");
        }

        infoAccountService.platformChange(agentNo, CS.SYS_ROLE_TYPE.AGENT, changeAmount, remark);
        return ApiRes.ok();
    }

    @PreAuthorize("hasAuthority('ENT_AGENT_INFO_AUDIT')")
    @MethodLog(remark = "审核服务商")
    @RequestMapping(value = "/audit/{agentNo}", method = RequestMethod.PUT)
    public ApiRes audit(@PathVariable("agentNo") String agentNo) {

        // 审核备注
        String auditRemark = getValString("auditRemark");
        // 审核状态
        Byte auditState = getValByteDefault("auditState", CS.NO);
        // 审核成功/驳回
        agentInfoService.auditInfo(agentNo, auditState, auditRemark);

        return ApiRes.ok();
    }

    /**
     * 统计
     **/
    @PreAuthorize("hasAuthority('ENT_AGENT_INFO_COUNT')")
    @GetMapping(value = "/count")
    public ApiRes count() {

        AgentInfo agentInfo = getObject(AgentInfo.class);
        LambdaQueryWrapper<AgentInfo> wrapper = AgentInfo.gw();

        selectParams(agentInfo, wrapper);
        Map<String, Object> result = agentInfoService.countByAccount(wrapper);

        return ApiRes.ok(result);
    }

    /**
     * @author: xiaoyu
     * @date: 2023/7/10 8:46
     * @describe: 查询公共条件
     */
    public void selectParams(AgentInfo agentInfo, LambdaQueryWrapper<AgentInfo> wrapper) {
        wrapper.eq(StringUtils.isNotEmpty(agentInfo.getAgentNo()), AgentInfo::getAgentNo, agentInfo.getAgentNo());
        wrapper.eq(StringUtils.isNotEmpty(agentInfo.getPid()), AgentInfo::getPid, agentInfo.getPid());
        wrapper.eq(StringUtils.isNotEmpty(agentInfo.getIsvNo()), AgentInfo::getIsvNo, agentInfo.getIsvNo());
        wrapper.like(StringUtils.isNotEmpty(agentInfo.getAgentName()), AgentInfo::getAgentName, agentInfo.getAgentName());
        wrapper.eq(agentInfo.getState() != null, AgentInfo::getState, agentInfo.getState());
        wrapper.eq(agentInfo.getAddAgentFlag() != null, AgentInfo::getAddAgentFlag, agentInfo.getAddAgentFlag());
        wrapper.eq(agentInfo.getAddMchFlag() != null, AgentInfo::getAddMchFlag, agentInfo.getAddMchFlag());
        wrapper.like(StringUtils.isNotEmpty(agentInfo.getContactTel()), AgentInfo::getContactTel, agentInfo.getContactTel());
        wrapper.like(StringUtils.isNotEmpty(agentInfo.getLoginUsername()), AgentInfo::getLoginUsername, agentInfo.getLoginUsername());
        wrapper.eq(agentInfo.getLevel() != null, AgentInfo::getLevel, agentInfo.getLevel());
    }
}
