package com.sqx.modules.app.controller.app;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.sqx.common.annotation.Debounce;
import com.sqx.common.utils.ApiAccessLimitUtil;
import com.sqx.common.utils.DataLimitUtil;
import com.sqx.common.utils.DesensitizedUtil;
import com.sqx.common.utils.Result;
import com.sqx.modules.app.annotation.Login;
import com.sqx.modules.app.annotation.LoginUser;
import com.sqx.modules.app.dto.AuthRespDTO;
import com.sqx.modules.app.entity.TbUserBlacklist;
import com.sqx.modules.app.entity.UserEntity;
import com.sqx.modules.app.entity.UserInfo;
import com.sqx.modules.app.mapper.TbUserBlacklistMapper;
import com.sqx.modules.app.service.AliService;
import com.sqx.modules.app.service.AppService;
import com.sqx.modules.app.service.UserInfoService;
import com.sqx.modules.app.service.UserService;
import com.sqx.modules.common.service.CommonInfoService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;

/**
 * APP登录授权
 *
 * @author mac
 */
@RestController
@RequestMapping("/app/user")
@Api(value = "APP管理", tags = {"APP管理"})
@Slf4j
public class AppController {

    @Autowired
    private UserService userService;
    @Autowired
    private AppService appService;
    @Autowired
    private CommonInfoService commonRepository;
    private final UserInfoService userInfoService;
    private final AliService aliService;
    @Autowired
    private TbUserBlacklistMapper tbUserBlacklistMapper;

    public AppController(UserInfoService userInfoService, AliService aliService) {
        this.userInfoService = userInfoService;
        this.aliService = aliService;
    }

    @PostMapping("/authenticationRegister")
    @ApiOperation("认证创建账号")
    public Result authenticationRegister(@RequestBody JSONObject jsonObject, HttpServletRequest request) {
        return userService.authenticationRegister(jsonObject, request);
    }

    @Login
    @PostMapping("/getNewUserRed")
    @ApiOperation("领取新用户红包")
    public Result getNewUserRed(@RequestAttribute Long userId) {
        return userService.getNewUserRed(userId);
    }

    @Login
    @RequestMapping(value = "/updatePwd", method = RequestMethod.POST)
    @ResponseBody
    @ApiOperation("用户端修改密码")
    public Result updatePwd(@LoginUser UserEntity user, String pwd, String oldPwd) {
        if (!user.getPassword().equals(DigestUtils.sha256Hex(oldPwd))) {
            return Result.error("原始密码不正确！");
        }
        if (pwd.equals(oldPwd)) {
            return Result.error("新密码不能与旧密码相同！");
        }
        user.setPassword(DigestUtils.sha256Hex(pwd));
        userService.update(user, new LambdaQueryWrapper<UserEntity>().eq(UserEntity::getUserId, user.getUserId()));
        return Result.success();
    }

    @Login
    @RequestMapping(value = "/updatePhone", method = RequestMethod.POST)
    @ApiOperation("用户端换绑手机号")
    @ResponseBody
    public Result updatePhone(@RequestAttribute("userId") Long userId, @RequestParam String phone, @RequestParam String msg) {
        return userService.updatePhone(phone, msg, userId);
    }

    @Login
    @RequestMapping(value = "/bindAlipay", method = RequestMethod.POST)
    @ApiOperation("绑定支付宝")
    @ResponseBody
    @Debounce(interval = 3000, value = "#userId")
    public Result bindAlipay(@RequestAttribute("userId") Long userId,
                             @RequestParam String zhiFuBao,
                             @RequestParam String certName
    ) {
        if (StrUtil.isAllBlank(zhiFuBao, certName)) {
            return Result.error("支付宝账号或姓名不能为空");
        }
        if(zhiFuBao.contains("*") || certName.contains("*")){
            return Result.success();
        }
        UserEntity userEntity = userService.getById(userId);
        if (zhiFuBao.equals(userEntity.getZhiFuBao()) && certName.equals(userEntity.getZhiFuBaoName())) {
            return Result.success();
        }
        int count = userService.count(new QueryWrapper<UserEntity>()
                .ne("user_id", userId)
                .eq("zhi_fu_bao_name", certName)
                .eq("zhi_fu_bao", zhiFuBao));
        if (count > 0) {
            return Result.error("支付宝信息修改失败: 此支付宝账号已被绑定");
        }
        UserInfo userInfo = userInfoService.getByUserId(userId);
        if (userInfo != null) {
            if (StrUtil.isNotBlank(userInfo.getCertName()) && !certName.equals(userInfo.getCertName())) {
                return Result.error("支付宝信息修改失败: 姓名与实名认证信息不相符");
            }
        }
        if (!DataLimitUtil.isAccessAllowed(zhiFuBao + certName, Integer.parseInt(commonRepository.findOne(924).getValue()), "month")) {
            return Result.error("支付宝信息修改失败: 相同支付宝账号每月可绑定次数已用完");
        }

        if (!ApiAccessLimitUtil.isAccessAllowed(userId.toString(), "updateZFB", Integer.parseInt(commonRepository.findOne(925).getValue()), "month")) {
            return Result.error("支付宝信息修改失败: 每月可修改次数已用完,请联系管理员");
        }

        userEntity.setZhiFuBao(zhiFuBao);
        userEntity.setZhiFuBaoName(certName);
        userService.update(userEntity, new LambdaQueryWrapper<UserEntity>().eq(UserEntity::getUserId, userId));
        return Result.success();
    }

    @Login
    @RequestMapping(value = "/realNameAuth", method = RequestMethod.POST)
    @ApiOperation("实名认证")
    @ResponseBody
    @Debounce(interval = 3000, value = "#userId")
    public Result bindAlipay(@RequestAttribute("userId") Long userId,
                             @RequestParam String certName,
                             @RequestParam String certNum,
                             @RequestParam String accountNo,
                             @RequestParam String mobile
    ) {
        if (StrUtil.isAllBlank(certName, certNum, accountNo, mobile)) {
            return Result.error("真实姓名、身份证号码、银行卡号、银行预留手机号缺一不可");
        }
        if(certNum.contains("*") || accountNo.contains("*") || mobile.contains("*")){
            return Result.success();
        }
        int count = userInfoService.count(Wrappers.<UserInfo>lambdaQuery()
                .eq(UserInfo::getUserId, userId).eq(UserInfo::getCertName, certName)
                .eq(UserInfo::getCertNo, certNum)
                .isNotNull(UserInfo::getAccountNo)
                .isNotNull(UserInfo::getMobile)
                .isNotNull(UserInfo::getBankName)
        );
        if (count > 0) {
            return Result.error("已完成实名认证，无需重复操作");
        }
        count = userInfoService.count(Wrappers.<UserInfo>lambdaQuery()
                .ne(UserInfo::getUserId, userId)
                .eq(UserInfo::getCertName, certName)
                .eq(UserInfo::getCertNo, certNum)
        );
        if (count > 0) {
            return Result.error("实名认证失败: 此身份证信息已被其他账号绑定");
        }
        if (!ApiAccessLimitUtil.getCertAuthIsAccessAllowed(String.valueOf(userId), "updateAuthCertInfo", 5)) {
            return Result.error("实名修改失败: 每月可修改次数已用完，请联系管理员");
        }
        AuthRespDTO resp = aliService.auth(certName, certNum, accountNo, mobile);
        UserInfo userInfo = userInfoService.getByUserId(userId);
        userInfo.setCertName(certName);
        userInfo.setCertNo(certNum);
        userInfo.setAccountNo(accountNo);
        userInfo.setMobile(mobile);
        userInfo.setBankName(resp.getBankName());
        userInfo.setRespJson(resp.getRespJson());
        userInfo.setUpdateTime(DateUtil.date());
        boolean update = userInfoService.update(userInfo, new LambdaQueryWrapper<UserInfo>().eq(UserInfo::getUserId, userId).eq(UserInfo::getId, userInfo.getId()));
        if (!update) {
            return Result.error("实名修改失败: 请稍后重试");
        }
        ApiAccessLimitUtil.setCertAuthIsAccessAllowed(String.valueOf(userId), "updateAuthCertInfo", 1, "month");
        // 校验实名信息是否在黑名单里面
        count = tbUserBlacklistMapper.selectCount(new LambdaQueryWrapper<TbUserBlacklist>().eq(TbUserBlacklist::getIdCardNo, certNum));
        if (count > 0) {
            UserEntity userEntity = userService.getById(userId);
            userEntity.setStatus(0);
            userService.update(userEntity, new LambdaQueryWrapper<UserEntity>().eq(UserEntity::getUserId, userId));
            log.warn("异常行为用户：实名信息异常: {}", userId);
            return Result.error("异常行为: 您的实名信息存在异常行为");
        }
        return Result.success();
    }


    @Login
    @RequestMapping(value = "/updateUsers", method = RequestMethod.POST)
    @ApiOperation("用户修改个人信息")
    @ResponseBody
    public Result updateUsers(@RequestAttribute("userId") Long userId, @RequestBody UserEntity userEntity) {
        userEntity.setUserId(userId);
        userService.update(null, Wrappers.<UserEntity>lambdaUpdate().eq(UserEntity::getUserId, userId)
                .set(StrUtil.isNotBlank(userEntity.getAvatar()), UserEntity::getAvatar, userEntity.getAvatar())
                .set(StrUtil.isNotBlank(userEntity.getUserName()), UserEntity::getUserName, userEntity.getUserName())
        );
        return Result.success();
    }

    @Login
    @RequestMapping(value = "/updateUserImageUrl", method = RequestMethod.POST)
    @ApiOperation("用户修改头像")
    @ResponseBody
    public Result updateUserImageUrl(@LoginUser UserEntity user, String avatar) {
        user.setAvatar(avatar);
        userService.update(user, new LambdaQueryWrapper<UserEntity>().eq(UserEntity::getUserId, user.getUserId()));
        return Result.success();
    }

    @Login
    @RequestMapping(value = "/updateUserName", method = RequestMethod.POST)
    @ApiOperation("用户修改昵称")
    @ResponseBody
    public Result updateUserName(@LoginUser UserEntity user, String userName) {
        user.setUserName(userName);
        userService.update(user, new LambdaQueryWrapper<UserEntity>().eq(UserEntity::getUserId, user.getUserId()));
        return Result.success();
    }

    @Login
    @RequestMapping(value = "/selectUserById", method = RequestMethod.GET)
    @ApiOperation("获取用户详细信息")
    @ResponseBody
    public Result selectUserById(@LoginUser UserEntity user) {
        UserInfo userInfo = userInfoService.getByUserId(user.getUserId());
        userInfo.setRespJson(null);
        if (StrUtil.isNotEmpty(userInfo.getAccountNo())) {
            userInfo.setAccountNo(DesensitizedUtil.bankCard(userInfo.getAccountNo()));
        }
        if (StrUtil.isNotEmpty(userInfo.getMobile())) {
            userInfo.setMobile(DesensitizedUtil.mobilePhone(userInfo.getMobile()));
        }
        if (StrUtil.isNotEmpty(userInfo.getCertNo())) {
            userInfo.setCertNo(DesensitizedUtil.idCardNum(userInfo.getCertNo(), 3, 2));
        }
        if (StrUtil.isNotEmpty(user.getZhiFuBao())) {
            if (Validator.isEmail(user.getZhiFuBao())) {
                user.setZhiFuBao(DesensitizedUtil.email(user.getZhiFuBao()));
            } else {
                user.setZhiFuBao(DesensitizedUtil.mobilePhone(user.getZhiFuBao()));
            }
        }
        Map<String, Object> map = BeanUtil.beanToMap(user);
        map.putAll(BeanUtil.beanToMap(userInfo));
        if (StrUtil.isBlank(user.getZhiFuBaoName()) && StrUtil.isNotBlank(userInfo.getCertName())) {
            map.put("zhiFuBaoName", userInfo.getCertName());
        }
        return Result.success().put("data", map);
    }


    @RequestMapping(value = "/selectNewApp", method = RequestMethod.GET)
    @ApiOperation("升级检测")
    @ResponseBody
    public Result selectNewApp() {
        return Result.success().put("data", appService.selectNewApp());
    }

    @GetMapping("/openId/{code:.+}/{userId}")
    @ApiOperation("根据code获取openid")
    public Result getOpenid(@PathVariable("code") String code, @PathVariable("userId") Long userId) {
        return userService.getOpenId(code, userId);
    }

    @RequestMapping(value = "/updateClientId", method = RequestMethod.GET)
    @ApiOperation("绑定ClientId")
    @ResponseBody
    public Result updateClientId(String clientId, Long userId, Integer sysPhone) {
        userService.updateUserClientIdIsNull(clientId);
        UserEntity userEntity = new UserEntity();
        userEntity.setSysPhone(sysPhone);
        userEntity.setUserId(userId);
        userEntity.setClientid(clientId);
        userService.update(userEntity, new LambdaQueryWrapper<UserEntity>().eq(UserEntity::getUserId, userId));
        return Result.success();
    }

}
