package com.jeequan.jeepay.mch.ctrl;

import cn.hutool.core.codec.Base64;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.bizcommons.manage.auth.AuthByQrcodeManage;
import com.jeequan.jeepay.converter.BaseConverter;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.cache.ITokenService;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.jwt.JWTPayload;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.model.security.JeeUserDetails;
import com.jeequan.jeepay.core.utils.SpringBeansUtil;
import com.jeequan.jeepay.core.utils.TreeDataBuilder;
import com.jeequan.jeepay.core.utils.google.GoogleAuth;
import com.jeequan.jeepay.db.entity.MchConfig;
import com.jeequan.jeepay.db.entity.MchInfo;
import com.jeequan.jeepay.db.entity.SysEntitlement;
import com.jeequan.jeepay.db.entity.SysUserEntity;
import com.jeequan.jeepay.mch.service.AuthService;
import com.jeequan.jeepay.service.impl.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 当前登录者的信息相关接口
 *
 * @author terrfly
 * @modify zhuxiao
 * @date 2021-04-27 15:50
 */
@RestController
@RequestMapping("/api/current")
public class CurrentUserController extends CommonCtrl {

    @Autowired
    private SysEntitlementService sysEntitlementService;
    @Autowired
    private SysUserService sysUserService;
    @Autowired
    private SysUserAuthService sysUserAuthService;
    @Autowired
    private MchConfigService mchConfigService;
    @Autowired
    private MchInfoService mchInfoService;
    @Autowired
    private StoreUserWorkRecordService storeUserWorkRecordService;
    @Autowired
    private BaseConverter baseConverter;

    @RequestMapping(value = "/user", method = RequestMethod.GET)
    public ApiRes currentUserInfo() {

        ///当前用户信息
        JeeUserDetails jeeUserDetails = getCurrentUser();
        SysUserEntity user = sysUserService.getById(jeeUserDetails.getSysUser().getSysUserId());

        //1. 当前用户所有权限ID集合
        List<String> entIdList = new ArrayList<>();
        jeeUserDetails.getAuthorities().forEach(r -> entIdList.add(r.getAuthority()));

        List<SysEntitlement> allMenuList = new ArrayList<>();    //所有菜单集合

        //2. 查询出用户所有菜单集合 (包含左侧显示菜单 和 其他类型菜单 )
        if (!entIdList.isEmpty()) {
            allMenuList = sysEntitlementService.list(SysEntitlement.gw()
                    .in(SysEntitlement::getEntId, entIdList)
                    .in(SysEntitlement::getEntType, Arrays.asList(CS.ENT_TYPE.MENU_LEFT, CS.ENT_TYPE.MENU_OTHER))
                    .eq(SysEntitlement::getSysType, CS.SYS_ROLE_TYPE.MCH)
                    .eq(SysEntitlement::getState, CS.PUB_USABLE));
        }

        //4. 转换为json树状结构
        JSONArray jsonArray = (JSONArray) JSON.toJSON(allMenuList);
        List<JSONObject> allMenuRouteTree = new TreeDataBuilder(jsonArray,
                "entId", "pid", "children", "entSort", true)
                .buildTreeObject();

        //1. 所有权限ID集合
        user.addExt("entIdList", entIdList);
        user.addExt("allMenuRouteTree", allMenuRouteTree);
        user.addExt("mchType", jeeUserDetails.getMchType());
        MchInfo mchInfo = mchInfoService.getById(getCurrentMchNo());
        user.addExt("mchLevel", mchInfo.getMchLevel());

        // 程序是否支持服务商
        user.addExt("isHasAgentEnt", SysConfigService.IS_HAS_AGENT_ENT);

        // 程序是否支持会员
        user.addExt("isHasMemberEnt", SysConfigService.IS_HAS_MEMBER_ENT);
        // 商户是否开启会员功能
        Byte memberModelState = mchConfigService.getConfigValByMchNoAndKey(mchInfo.getMchNo(), MchConfig.SELF_MEMBER_MODEL_STATE, Byte.class);
        // 商户会员功能显示开关
        if (memberModelState == null || memberModelState == CS.NO) {
            user.addExt("isHasMemberEnt", false);
        }

        // 查询用户app推送设备是否注册
        // mchAppPushInfoService.saveMchCid(getValString("cid1"), getValString("cid2"), getCurrentMchNo(), getCurrentUser().getSysUserId());

        // 查询当前登录帐号是否为微信小程序审核帐号
        boolean isWxAuditUser = false;
        String wxAuditMchNo = sysConfigService.getById("wxAuditUser").getConfigVal();
        if (StringUtils.isNotBlank(wxAuditMchNo) && (wxAuditMchNo.equals("*") || wxAuditMchNo.contains(getCurrentMchNo()))) {
            isWxAuditUser = true;
        }
        user.addExt("isWxAuditUser", isWxAuditUser);
        //获取商户简称
        user.addExt("shortName", mchInfo.getMchShortName());
        //获取支付密码
        user.addExt("sipw", mchInfo.getSipw() == null ? "2" : "1");

        // 刷脸设备上下班状态
        if (JWTPayload.LOGIN_PAGE_TYPE.FACE_APP.equals(getCurrentUser().getLoginType())) {
            user.addExt("workState", storeUserWorkRecordService.getWorkState(getCurrentUser().getStoreIdList().get(0), user.getSysUserId()));
        }

        return ApiRes.ok(user);
    }


    /**
     * 修改个人信息
     */
    @MethodLog(remark = "修改个人信息")
    @RequestMapping(value = "/user", method = RequestMethod.PUT)
    public ApiRes modifyCurrentUserInfo() {

        //修改头像
        String avatarUrl = getValString("avatarUrl");
        String realname = getValString("realname");
        Byte sex = getValByte("sex");
        //编辑预留信息
        String safeWord = getValString("safeWord");
        SysUserEntity updateRecord = new SysUserEntity();
        updateRecord.setSysUserId(getCurrentUser().getSysUser().getSysUserId());
        if (StringUtils.isNotEmpty(avatarUrl)) {
            updateRecord.setAvatarUrl(avatarUrl);
        }
        if (StringUtils.isNotEmpty(realname)) {
            updateRecord.setRealname(realname);
        }
        if (sex != null) {
            updateRecord.setSex(sex);
        }
        if (StringUtils.isNotEmpty(safeWord)) {
            updateRecord.setSafeWord(safeWord);
        }
        sysUserService.updateById(updateRecord);

        SysUserEntity sysUserEntity = sysUserService.getById(getCurrentUser().getSysUser().getSysUserId());
        //保存redis最新数据
        JeeUserDetails currentUser = getCurrentUser();
        currentUser.setSysUser(baseConverter.toModel(sysUserEntity));
        ITokenService.refData(currentUser);

        return ApiRes.ok();
    }


    /**
     * modifyPwd
     */
    @MethodLog(remark = "修改密码")
    @RequestMapping(value = "modifyPwd", method = RequestMethod.PUT)
    public ApiRes modifyPwd() throws BizException {

        Long opSysUserId = getCurrentUser().getSysUser().getSysUserId();

        //更改密码，验证当前用户信息
        String currentUserPwd = Base64.decodeStr(getValStringRequired("originalPwd")); //当前用户登录密码
        //验证当前密码是否正确
        if (!sysUserAuthService.validateCurrentUserPwd(currentUserPwd)) {
            throw new BizException("原密码验证失败！");
        }

        String opUserPwd = Base64.decodeStr(getValStringRequired("confirmPwd"));

        // 验证原密码与新密码是否相同
        if (opUserPwd.equals(currentUserPwd)) {
            throw new BizException("新密码与原密码不能相同！");
        }

        sysUserAuthService.resetAuthInfo(opSysUserId, null, null, true, opUserPwd, CS.SYS_ROLE_TYPE.MCH);
        //调用登出接口
        return logout();
    }

    /**
     * 登出
     */
    @MethodLog(remark = "退出")
    @RequestMapping(value = "logout", method = RequestMethod.POST)
    public ApiRes logout() throws BizException {

        ITokenService.removeIToken(getCurrentUser().getCacheKey(), getCurrentUser().getSysUser().getSysUserId());
        return ApiRes.ok();
    }

    /**
     * MFA验证信息
     */
    @GetMapping("/mfaInfo")
    @MethodLog(remark = "MFA验证信息")
    public ApiRes mfaInfo() throws BizException {
        SysUserEntity currentUser = sysUserService.getById(getCurrentUser().getSysUserId());
        JSONObject resJson = new JSONObject();
        resJson.put("mfaBindState", currentUser.getMfaBindState());
        resJson.put("telPhone", currentUser.getTelphone());
        // 是否展示MFA绑定信息 [未绑定时显示]
        if (currentUser.getMfaBindState() == CS.NO) {
            String secretKey = sysUserService.getById(currentUser.getSysUserId()).getMfaSecretKey();
            // 更新用户验证秘钥
            if (StringUtils.isEmpty(secretKey)) {
                secretKey = GoogleAuth.generateSecretKey();
                sysUserService.updateMFASecret(currentUser.getSysUserId(), secretKey, null);
            }
            String qrcodeUrl = GoogleAuth.getQRBarcode(
                    sysConfigService.getOemConfig().getSysName() + "_商户" + "(" + currentUser.getTelphone() + ")"
                    , secretKey);
            resJson.put("mfaBindUrl", qrcodeUrl);
            resJson.put("mfaSecretKey", secretKey);
        }
        return ApiRes.ok(resJson);
    }

    /**
     * MFA验证 绑定
     */
    @RequestMapping(value = "mfaBind", method = RequestMethod.PUT)
    @MethodLog(remark = "MFA验证绑定")
    public ApiRes mfaBind() throws BizException {
        String verCode = getValStringRequired("verCode");
        Long userId = getCurrentUser().getSysUserId();
        // 验证验证码
        sysUserService.checkMFACode(userId, verCode);

        // 绑定MFA验证
        sysUserService.bindMFA(userId);
        return ApiRes.ok();
    }

    /**
     * MFA验证 解绑
     */
    @RequestMapping(value = "mfaRelieve", method = RequestMethod.PUT)
    @MethodLog(remark = "MFA验证解除")
    public ApiRes mfaRelieve() throws BizException {
        String verCode = getValStringRequired("verCode");
        Long userId = getCurrentUser().getSysUserId();
        // 验证验证码
        sysUserService.checkMFACode(userId, verCode);

        // 解除MFA验证
        sysUserService.relieveMFA(userId, CS.SYS_ROLE_TYPE.MCH);
        return ApiRes.ok();
    }

    /**
     * app扫码登录接口
     */
    @PostMapping("qrcode/login")
    public ApiRes loginQrcodeConfirm() {

        String qrcodeNo = getValStringRequired("qrcodeNo");
        String qrCodeStatus = getValStringRequired("qrcodeStatus");

        if (!StringUtils.equalsAny(qrCodeStatus, AuthByQrcodeManage.QRCODE_STATUS_SCANED, AuthByQrcodeManage.QRCODE_STATUS_CANCELED,
                AuthByQrcodeManage.QRCODE_STATUS_CONFIRMED)) {
            return ApiRes.customFail("qrcodeStatus错误");
        }

        // 更新状态：等待扫码 --> 已扫
        if (qrCodeStatus.equals(AuthByQrcodeManage.QRCODE_STATUS_SCANED)) {

            AuthByQrcodeManage.updateQrcodeStatusWaiting2Scaned(qrcodeNo);
            return ApiRes.ok();

            // 更新状态：已扫 --> 取消
        } else if (qrCodeStatus.equals(AuthByQrcodeManage.QRCODE_STATUS_CANCELED)) {

            AuthByQrcodeManage.updateQrcodeStatusScaned2Canceled(CS.SYS_ROLE_TYPE.MCH, qrcodeNo);
            return ApiRes.ok();

        }

        // 更新状态：已扫 --> 确认登录
        JSONObject tokenJSON = SpringBeansUtil.getBean(AuthService.class).authByAppQrcode(getCurrentUser().getSysUserId(), JWTPayload.LOGIN_PAGE_TYPE.WEB);

        // 更新状态：已扫 --> 确认登录
        AuthByQrcodeManage.updateQrcodeStatusScaned2Confirmed(qrcodeNo, tokenJSON.toJSONString());

        return ApiRes.ok();
    }

}
