package com.ruoyi.web.controller.app;

import com.fasterxml.jackson.annotation.JsonView;
import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.JsonViewProfile;
import com.ruoyi.common.core.domain.entity.SmUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.ServiceUtil;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.web.service.SysPasswordService;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.ss.realName.domain.enums.RealNameType;
import com.ruoyi.ss.risk.domain.RiskVO;
import com.ruoyi.ss.risk.service.RiskService;
import com.ruoyi.ss.risk.service.RiskValidator;
import com.ruoyi.ss.riskInfo.domain.RiskInfoVO;
import com.ruoyi.ss.riskInfo.service.RiskInfoService;
import com.ruoyi.ss.riskInfo.service.RiskInfoValidator;
import com.ruoyi.ss.user.domain.SmUserQuery;
import com.ruoyi.ss.user.domain.SmUserVO;
import com.ruoyi.ss.user.domain.dto.UserChangeMobileDTO;
import com.ruoyi.ss.user.domain.dto.UserRealNameDTO;
import com.ruoyi.ss.user.domain.dto.UserUpdatePasswordDTO;
import com.ruoyi.ss.user.service.ISmUserService;
import com.ruoyi.ss.user.service.UserAssembler;
import com.ruoyi.ss.user.service.UserConverter;
import com.ruoyi.system.domain.enums.verificationCode.CodeBusinessType;
import com.ruoyi.system.service.IVerificationCodeService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.Collections;
import java.util.List;
import java.util.Objects;

/**
 * 用户信息Controller
 * @author 辉
 * 2024/3/6
 */
@Api(tags = "用户信息")
@RestController
@RequestMapping("/app/user")
public class AppUserController extends BaseController {

    @Autowired
    private ISmUserService userService;

    @Autowired
    private IVerificationCodeService verificationCodeService;

    @Autowired
    private UserAssembler userAssembler;

    @Autowired
    private SysPasswordService passwordService;

    @Autowired
    private TokenService tokenService;

    @Autowired
    private UserConverter userConvert;

    @Autowired
    private RiskService riskService;

    @Autowired
    private RiskValidator riskValidator;

    @Autowired
    private RiskInfoService riskInfoService;

    @Autowired
    private RiskInfoValidator riskInfoValidator;

    @ApiOperation("获取当前登录前台用户的信息")
    @GetMapping("/userInfo")
    @JsonView(JsonViewProfile.AppMch.class)
    public AjaxResult userInfo() {
        // 查询
        SmUserVO user = userService.selectSmUserByUserId(getUserId());
        ServiceUtil.assertion(user == null, "用户不存在", HttpStatus.UNAUTHORIZED);

        List<SmUserVO> list = Collections.singletonList(user);
        userService.desensitization(list);
        userAssembler.assembleStoreCount(list);
        userAssembler.assembleDeviceCount(list);
        userAssembler.assembleWaitBonusAmount(list);
        userAssembler.assembleIsStaff(list);
        return AjaxResult.success(user);
    }

    @ApiOperation("使用旧密码修改密码")
    @PutMapping("/updatePassword")
    public AjaxResult updatePassword( @RequestBody @Validated UserUpdatePasswordDTO dto) {
        SmUserVO user = userService.selectSmUserByUserId(getUserId());
        if (user == null) {
            return error("用户不存在");
        }
        // 若有设置旧密码，则应该判断旧密码是否正确
        if (StringUtils.hasText(user.getPassword()) && !passwordService.matches(user, dto.getOldPassword())) {
            return error("旧密码错误");
        }

        return toAjax(userService.updatePassword(getUserId(), dto.getNewPassword()));
    }

    @ApiOperation("退出登录")
    @DeleteMapping("/logout")
    public AjaxResult logout() {
        // 删除用户缓存记录
        LoginUser loginUser = SecurityUtils.getLoginUser();
        tokenService.delLoginUser(loginUser.getToken());
        return success();
    }

    @ApiOperation("用户实名认证")
    @PutMapping("/realName")
    public AjaxResult realName(@RequestBody @Validated UserRealNameDTO dto) {
        dto.setType(RealNameType.NORMAL.getType());
        dto.setUserId(getUserId());
        return success(userService.realName(dto));
    }

    @ApiOperation("用户风控实名认证")
    @PutMapping("/riskRealName")
    public AjaxResult riskRealName(@RequestParam Long riskInfoId) {
        RiskInfoVO info = riskInfoService.selectRiskInfoByInfoId(riskInfoId);
        ServiceUtil.assertion(!riskInfoValidator.isUser(info, getUserId()), "风控信息不存在");
        return success(userService.riskRealName(info));
    }

    @ApiOperation("刷新用户实名认证结果")
    @GetMapping("/refreshRealName")
    public AjaxResult refreshRealName() {
        return AjaxResult.success("操作成功", userService.refreshRealName(getUserId()));
    }

    @ApiOperation("标记用户已读商户协议")
    @PutMapping("/readMchLicence")
    public AjaxResult readMchLicence() {
        return toAjax(userService.readMchLicence(getUserId()));
    }

    @ApiOperation("获取用户修改手机号的旧手机验证码")
    @GetMapping("/changeMobileCodeOld")
    public AjaxResult getChangeMobileCodeOld() {
        return success(userService.getChangeMobileCodeOld(getUserId()));
    }

    @ApiOperation("获取用户修改手机号的新手机验证码")
    @GetMapping("/changeMobileNewCode")
    public AjaxResult getChangeMobileNewCode(@RequestParam String mobile) {
        return success(verificationCodeService.sendMobileCode(mobile, CodeBusinessType.CHANGE_MOBILE_NEW));
    }

    @ApiOperation("通过验证码修改手机号")
    @PutMapping("/changeMobile")
    public AjaxResult changeMobile(@RequestBody UserChangeMobileDTO dto) {
        SmUserVO user = userService.selectSmUserByUserId(getUserId());
        ServiceUtil.assertion(user == null, "用户不存在");
        // 若有旧手机，则验证旧手机验证码
        if (user.getPhonenumber() != null) {
            boolean oldCheck = verificationCodeService.checkCode(user.getPhonenumber(), dto.getOldCode(), CodeBusinessType.CHANGE_MOBILE_OLD, false);
            ServiceUtil.assertion(!oldCheck, "旧手机验证码错误或已过期");
        }

        // 校验验证码
        boolean newCheck = verificationCodeService.checkCode(dto.getNewMobile(), dto.getNewCode(), CodeBusinessType.CHANGE_MOBILE_NEW, false);
        ServiceUtil.assertion(!newCheck, "新手机验证码错误或已过期");

        return success(userService.updateMobile(getUserId(), dto.getNewMobile()));
    }

    @ApiOperation("绑定微信手机号")
    @PutMapping("/bindWxMobile")
    public AjaxResult bindWxMobile(@ApiParam("微信手机号临时授权码") String mobileCode) {
        return toAjax(userService.bindWxMobile(getUserId(), mobileCode));
    }

    @ApiOperation("绑定支付宝手机号")
    @PutMapping("/bindAliMobile")
    public AjaxResult bindAliMobile(@ApiParam("支付宝手机号密文") @RequestBody String ciphertext) {
        return toAjax(userService.bindAliMobile(getUserId(), ciphertext));
    }

    @ApiOperation("修改用户设置")
    @PutMapping("/updateSetting")
    public AjaxResult updateSetting(@RequestBody SmUser data) {
        data.setUserId(getUserId());
        return toAjax(userService.updateSmUser(userConvert.toUserSettingByApp(data)));
    }

    @ApiOperation("通过精准手机号查询用户列表")
    @GetMapping("/getByEqPhone")
    @JsonView(JsonViewProfile.App.class)
    public AjaxResult getByEqPhone(String eqPhonenumber) {
        return success(userService.selectUserByPhone(eqPhonenumber));
    }
}
