/*
 * Copyright (c) 2023 codvision.com All Rights Reserved.
 */

package com.codvision.auth.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.json.JSONObject;
import com.aliyuncs.exceptions.ClientException;
import com.codvision.auth.core.AuthCaptchaService;
import com.codvision.auth.entity.UserOrgRole;
import com.codvision.auth.entity.vo.SysUserVO;
import com.codvision.auth.service.ISysUserService;
import com.codvision.auth.support.SendSms;
import com.codvision.auth.support.UserContext;
import com.codvision.authcore.bean.SysUserBean;
import com.codvision.authcore.service.IAuthService;
import com.codvision.authcore.util.AuthUtil;
import com.codvision.base.service.ISysConfigService;
import com.codvision.cachecore.utils.RedisUtil;
import com.codvision.commoncore.common.ResponseEntity;
import com.codvision.commoncore.exception.AuthException;
import com.codvision.commoncore.exception.BusinessException;
import com.codvision.commoncore.utils.Md5Utils;
import com.codvision.webcore.annotation.ApiSecret;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.TimeUnit;

import static com.codvision.auth.support.CacheContants.USER_LOGIN_MOBILE_CODE;

/**
 * 系统用户模块
 *
 * @author lingee
 * @date 2023/11/9
 */
@Slf4j
@RestController
@RequestMapping("/v1/sysUser")
@Api(tags = "用户端-系统用户模块")
public class SysUserController {

    @Resource
    private ISysUserService sysUserService;

    @Resource
    private ISysConfigService sysConfigService;

    @Resource
    @Lazy
    private IAuthService authService;

    @Resource
    private AuthCaptchaService authCaptchaService;

    @PostMapping("/resetPwd")
    @ApiOperation(value = "重置密码", notes = "重置密码接口")
    public ResponseEntity<String> resetPwd(@ApiParam(value = "用户Id列表", required = true) @RequestBody List<Integer> userIds) {
        Assert.notEmpty(userIds, "用户Id不能为空");
        ResponseEntity<String> responseEntity = new ResponseEntity<>();
        sysUserService.batchResetPwd(userIds);
        return responseEntity.ok();
    }

    @PostMapping("/activeOrgRole")
    @ApiOperation("切换用户所属组织及对应角色")
    public ResponseEntity<SysUserVO> activeOrgRole(@RequestBody UserOrgRole userOrgRole) {
        ResponseEntity<SysUserVO> responseEntity = new ResponseEntity<>();
        SysUserVO user = UserContext.get();
        if (null == user) {
            throw new BusinessException(10002);
        }

        if (userOrgRole.getRoleId() == null || userOrgRole.getOid() == null) {
            throw new BusinessException(30002);
        }

        userOrgRole.setUid(user.getId());
        sysUserService.activeOrgRole(userOrgRole, user);
        UserContext.set(user);
        return responseEntity.data(user);
    }

    @PostMapping("/login")
    @ApiOperation("用户账号密码登录")
    public ResponseEntity<SysUserBean> login(@RequestParam(value = "loginName") String loginName,
                                             @RequestParam(value = "password") String password,
                                             @RequestParam(value = "code", required = false) String code,
                                             @RequestParam(value = "reqNo", required = false) String reqNo,
                                             @RequestParam(value = "captchaVerification", required = false) String captchaVerification) {
        authCaptchaService.check(code, reqNo, captchaVerification);
        ResponseEntity<SysUserBean> responseEntity = new ResponseEntity<>();
        SysUserBean sysUser = authService.loginByUsernameAndPassword(loginName, password);
        return responseEntity.data(sysUser);
    }

    @GetMapping("/pwdRegularCheck")
    @ApiOperation("用户密码定期更新检查")
    public ResponseEntity<Boolean> pwdRegularCheck() {
        ResponseEntity<Boolean> responseEntity = new ResponseEntity<>();
        SysUserVO userVO = UserContext.get();
        if (userVO == null) {
            throw new BusinessException(10002);
        }
        return responseEntity.data(sysUserService.isRenewPwd(userVO.getLoginName()));
    }

    @ApiSecret(ignore = true)
    @PostMapping("/quickLogin")
    @ApiOperation("一键登录")
    public ResponseEntity<SysUserVO> quickLogin(@RequestParam(value = "token") String token,
                                                @RequestParam(value = "userInformation") String userInformation) {
        ResponseEntity<SysUserVO> responseEntity = new ResponseEntity<>();
        if (StringUtils.isBlank(token) || StringUtils.isBlank(userInformation)) {
            throw new BusinessException(30002);
        }

        return loginByMobile(responseEntity, sysUserService.quickLogin(token, userInformation));
    }

    private ResponseEntity<SysUserVO> loginByMobile(ResponseEntity<SysUserVO> responseEntity, String mobile) {
        sysUserService.loginByMobile(mobile);

        SysUserVO user = sysUserService.getDetailByLoginName(mobile);
        if (null == user) {
            throw new AuthException("账号不存在！");
        }
        SysUserBean sysUser = UserContext.set(user);
        user.setToken(sysUser.getToken());
        return responseEntity.ok().data(user);
    }

    @ApiSecret(ignore = true)
    @PostMapping("/loginSignature")
    @ApiOperation("用户单点登录")
    public ResponseEntity<SysUserVO> loginSignature(@RequestParam(value = "loginName") String loginName,
                                                    @RequestParam(value = "signature") String signature,
                                                    @RequestParam(value = "ts") Long ts) {
        ResponseEntity<SysUserVO> responseEntity = new ResponseEntity<>();
        if (Math.abs(ts - System.currentTimeMillis()) > 10 * 60 * 1000) {
            throw new BusinessException(10000, "时间戳错误");
        }

        String md5 = Md5Utils.getMd5(loginName + ts + "codvision");
        if (!md5.equals(signature)) {
            throw new BusinessException(10001);
        }

        SysUserVO user = sysUserService.getDetailByLoginName(loginName);
        if (null == user) {
            throw new AuthException("账号不存在！");
        }
        SysUserBean sysUser = UserContext.set(user);
        user.setToken(sysUser.getToken());
        return responseEntity.ok().data(user);
    }

    @PostMapping("/loginByMobile")
    @ApiOperation("用户登录(手机验证码)")
    public ResponseEntity<SysUserVO> loginByMobile(@RequestParam(value = "mobile") String mobile,
                                                   @RequestParam(value = "code") String code) {
        ResponseEntity<SysUserVO> responseEntity = new ResponseEntity<>();
        if (StringUtils.isBlank(mobile) || StringUtils.isBlank(code)) {
            throw new BusinessException(30002);
        }

        String codeCache = RedisUtil.get(USER_LOGIN_MOBILE_CODE + mobile);
        if (StringUtils.isBlank(codeCache)) {
            throw new BusinessException(30002, "验证码已过期");
        }
        if (!code.equals(codeCache)) {
            throw new BusinessException(30001, "验证码错误");
        }

        return loginByMobile(responseEntity, mobile);
    }

    @PostMapping("/loginPasswordFreeByMobile")
    @ApiOperation("用户手机号免密登录(配合移动端修改)")
    public ResponseEntity<SysUserVO> loginPasswordFreeByMobile(@ApiParam(value = "手机号", required = true) @RequestParam(value = "mobile") String mobile) {
        ResponseEntity<SysUserVO> responseEntity = new ResponseEntity<>();
        if (StringUtils.isBlank(mobile)) {
            throw new BusinessException(30002);
        }
        return loginByMobile(responseEntity, mobile);
    }

    @PostMapping(value = "/verifyCode")
    @ApiOperation("获取手机验证码")
    public ResponseEntity<String> getVerificationCode(
            @RequestParam(value = "code", required = false) String code,
            @RequestParam(value = "reqNo", required = false) String reqNo,
            @RequestParam(value = "captchaVerification", required = false) String captchaVerification,
            @ApiParam(value = "手机号", required = true) @RequestParam(value = "mobile") String mobile) {
        authCaptchaService.check(code, reqNo, captchaVerification);
        ResponseEntity<String> responseEntity = new ResponseEntity<>();
        if (StringUtils.isBlank(mobile)) {
            throw new BusinessException(30002, "请输入手机号");
        }

        String phoneCode = RandomUtil.randomNumbers(6);
        JSONObject object = new JSONObject();
        object.put("product", "基础平台");
        object.put("code", phoneCode);
        try {
            SendSms sendSms = new SendSms(sysConfigService);
            boolean flag = sendSms.sendWithParam(mobile, "登录验证", "SMS_57155135", object.toString());
            if (flag) {
                RedisUtil.set(USER_LOGIN_MOBILE_CODE + mobile, phoneCode, 10, TimeUnit.MINUTES);
                return responseEntity.message("验证码发送成功！");
            }
        } catch (ClientException e) {
            log.error(e.getMessage());
        }

        return responseEntity.ok();
    }


    @GetMapping("/logout")
    @ApiOperation("退出登陆")
    public ResponseEntity<String> logout() {
        ResponseEntity<String> responseEntity = new ResponseEntity<>();

        UserContext.remove();
        return responseEntity.ok();
    }

    @ApiSecret(ignore = true)
    @PostMapping("/getUserInfo")
    @ApiOperation("根据登录状态获取用户信息")
    public ResponseEntity<SysUserVO> getUserInfo() {
        ResponseEntity<SysUserVO> responseEntity = new ResponseEntity<>();
        SysUserBean sysUser = AuthUtil.getCurrentUser();

        SysUserVO vo = new SysUserVO();
        BeanUtil.copyProperties(sysUser, vo);
        return responseEntity.ok().data(vo);
    }
}
