package com.bonus.auth.controller;

import cn.hutool.core.util.IdUtil;
import com.bonus.auth.mapper.AuthCustInfoMapper;
import com.bonus.common.core.constant.CacheConstants;
import com.bonus.auth.api.SmsCodeApi;
import com.bonus.constant.CustLoginTypeEnum;
import com.bonus.constant.DelFlagEnum;
import com.bonus.constant.LeConstants;
import com.bonus.domain.CustCasual;
import com.bonus.domain.CustInfo;
import com.bonus.domain.CustInfoAppIdLoginVO;
import com.bonus.auth.form.LoginBody;
import com.bonus.auth.mapper.AuthCustCasualMapper;
import com.bonus.auth.service.*;
import com.bonus.domain.SmsCodeVerifyDTO;
import com.bonus.utils.AesEncryptUtil;
import com.bonus.utils.id.Id;
import com.bonus.utils.SM4EncryptUtils;
import com.bonus.common.core.domain.R;
import com.bonus.common.core.exception.ServiceException;
import com.bonus.common.core.utils.JwtUtils;
import com.bonus.common.core.utils.StringUtils;
import com.bonus.common.core.web.domain.AjaxResult;
import com.bonus.common.redis.service.RedisService;
import com.bonus.common.security.auth.AuthUtil;
import com.bonus.common.security.utils.SecurityUtils;
import com.bonus.config.SystemConfig;
import com.bonus.system.api.RemoteConfigService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * Token 控制器
 * 处理登录、获取验证码、登出、刷新令牌和注册功能
 */
@RestController
@Slf4j
public class TokenController {
    @Resource
   private SystemConfig config;

    @Autowired
    private CustTokenService tokenService;

    @Autowired
    private SysLoginService sysLoginService;

    @Autowired
    private SysRecordLogService logService;

    @Autowired
    private RedisService redisService;

    @Resource
    private RemoteConfigService configService;

    @Autowired
    private SmsCodeApi smsCodeApi;

    @Autowired
    private AuthCustInfoMapper custInfoMapper;

    @Autowired
    private AuthCustCasualMapper authCustCasualMapper;

    private static final BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
    //private static final String CUST_LOGIN_TOKEN_KEY = "cust_login_tokens:";

//    @PostMapping("isLogin")
//    public R<?> isLogin(@RequestBody LoginBody form) {
//        LoginStrategy strategy = loginStrategyFactory.getStrategy(form.getLoginType());
//        if (strategy == null) {
//            return R.fail("不支持的登录方式");
//        }
//        if (form.getLoginType()== LoginType.EMAIL_OTP || form.getLoginType()== LoginType.PHONE_OTP ){
//            form.setPassword(form.getVerificationCode());
//        }
//        LoginUser login = strategy.login(form.getUsername(), form.getPassword());
//        return R.ok(tokenService.isLogin(String.valueOf(login.getSysUser().getUserId())));
//    }

    @PostMapping("cust-login")
    public R<?> login(@RequestBody LoginBody form) {
        /**对系统并发数进行判断*/
        long concurrency = 10000;
        AjaxResult result = configService.getConfigKey("sys.backend.concurrency");
        if (result.isSuccess())
        {
            concurrency = Long.parseLong(result.get("msg").toString());
        }
        Collection<String> keys = redisService.keys(CustTokenService.LOGIN_TOKEN + "*");
        if (keys.size() >= concurrency){
            return R.fail("当前系统用户并发数超过系统配置，请稍后再试");
        }
        CustInfoAppIdLoginVO loginUser = custLogin(form);
        Map<String, Object> map = tokenService.createToken(loginUser);
        loginUser.setToken((String) map.get(CustTokenService.ACCESS_TOKEN));
        loginUser.setExpireIn((Long) map.get(CustTokenService.EXPIRES_IN));
        loginUser.setLogin((boolean) map.get(CustTokenService.IS_LOGIN));
        return R.ok(loginUser);
    }

    private CustInfoAppIdLoginVO custLogin(LoginBody content) {
//        if (CharSequenceUtil.isNotBlank(content.getMobile())) {
//            content.setMobile(AesEncryptUtil.aesDecode(content.getMobile()));
//        }
        CustInfo custInfo = new CustInfo();
        if (CustLoginTypeEnum.NAME_PWD.key().equals(content.getLoginType())) {
            custInfo.setCustName(SM4EncryptUtils.sm4Encryptbyconfig(content.getCustName()));
        } else if (CustLoginTypeEnum.NAME_CUST_NUM_PWD.key().equals(content.getLoginType())) {
            custInfo.setCustName(SM4EncryptUtils.sm4Encryptbyconfig(content.getCustName()));
            custInfo.setCustNum(content.getCustNum());
        } else if (CustLoginTypeEnum.TEL_PWD.key().equals(content.getLoginType())) {
            custInfo.setMobile(SM4EncryptUtils.sm4Encryptbyconfig(content.getMobile()));
        } else if (CustLoginTypeEnum.TEL_CODE.key().equals(content.getLoginType())) {
            SmsCodeVerifyDTO smsCodeVerifyDTO = new SmsCodeVerifyDTO();
            smsCodeVerifyDTO.setCode(content.getCode());
            smsCodeVerifyDTO.setTelephoneNumber(content.getMobile());
            boolean flag = this.smsCodeApi.verifySmsCode(smsCodeVerifyDTO, CacheConstants.VERIFICATION_CODE);
            if (!flag) {
                throw new ServiceException("验证码错误");
            }
            custInfo.setMobile(SM4EncryptUtils.sm4Encryptbyconfig(content.getMobile()));
        } else {
            if (!CustLoginTypeEnum.ID_CARD_PWD.key().equals(content.getLoginType())) {
                throw new ServiceException("参数错误");
            }
            custInfo.setIdCard(SM4EncryptUtils.sm4Encryptbyconfig(content.getIdCard()));
        }
        CustInfoAppIdLoginVO result = this.custInfoMapper.selectLoginInfo(custInfo);
        if (Objects.isNull(result)) {
            throw new ServiceException("未找到用户");
        } else {
            result.setCustIdStr(result.getCustId().toString());
            if (CustLoginTypeEnum.getNeedPasswordLoginTypeToMap().containsKey(content.getLoginType())) {
                content.setPassword(AesEncryptUtil.aesDecode(content.getPassword()));
                if (!encoder.matches(content.getPassword(), result.getPwd())) {
                    throw new ServiceException("密码错误");
                }
            }
            logService.saveLogin(custInfo.getCustName() + "" + custInfo.getMobile(), "登录", "登录成功", null, "成功");
            return this.addOrUpdateCustCasual(content.getSourceType(), result);
        }
    }

    public static void main(String[] args) {
        System.out.println(encoder.encode("Bonus$2026"));
        boolean flag = encoder.matches("Bonus$2026", "$2a$10$vrcmG0TyvgH5tS9g8ptaVOK2K3pYWVAa13SWEK7pQBGRtNAPlGV7O");
        System.out.println(flag);
    }

    public CustInfoAppIdLoginVO addOrUpdateCustCasual(Integer sourceType, CustInfoAppIdLoginVO result) {
        Long custId = result.getCustId();
        CustCasual custCasual = this.authCustCasualMapper.selectCustCasualByCustId(custId, sourceType, DelFlagEnum.DEL_FALSE.key());
        String openid;
        if (Objects.isNull(custCasual)) {
            CustCasual insertCasual = new CustCasual();
            openid = IdUtil.simpleUUID();
            insertCasual.setCasualId(Id.next());  //TODO, NPE
            insertCasual.setCasualName(SM4EncryptUtils.sm4Decrypt(result.getCustName()));
            insertCasual.setCustId(result.getCustId());
            insertCasual.setMobile(SM4EncryptUtils.sm4Decrypt(result.getMobile()));
            insertCasual.setOpenid(openid);
            insertCasual.setSourceType(sourceType);
            this.authCustCasualMapper.addCustCasual(insertCasual);
        } else {
            openid = custCasual.getOpenid();
            if (StringUtils.isBlank(openid)) {
                openid = IdUtil.simpleUUID();
                this.authCustCasualMapper.updateCustCasual(custCasual);
            }
        }

        result.setOpenid(openid);
        result.setCustName(SM4EncryptUtils.sm4Decrypt(result.getCustName()));
        result.setMobile(SM4EncryptUtils.sm4Decrypt(result.getMobile()));
        return result;
    }

    /**
     * 获取手机验证码
     *
     * @param form 登录表单
     * @return 验证码发送结果
     */
    @PostMapping("getPhoneCode")
    public R<?> getPhoneCode(@RequestBody LoginBody form) {
        return sysLoginService.getPhoneCode(form.getMobile(), form.getVerificationCodeType());
    }

    /**
     * 用户登出
     *
     * @param request HTTP 请求
     * @return 登出结果
     */
    @PostMapping("cust-logout")
    public R<?> logout(HttpServletRequest request, @RequestHeader Map<String, String> headers) {
        try {
            String token = SecurityUtils.getToken(request);
            if (StringUtils.isNotEmpty(token)) {
                String key = JwtUtils.getUserKey(token);
                boolean key1 = tokenService.isKey(key);
                if (key1) {
                    String username = JwtUtils.getUserName(token);
                    String userId = JwtUtils.getUserId(token);
                    AuthUtil.logoutByToken(token);
                    tokenService.delExistingToken(Long.valueOf(userId));
                    Long custId = Long.parseLong(headers.get("custId"));
                    String openId = (String)headers.get("openid");
                    authCustCasualMapper.updateByCustIdAndOpenId(custId, LeConstants.COMMON_NO, openId);
                    sysLoginService.logout(username, userId);
                    logService.saveLogout(username, "退出登录", "退出成功", userId, "成功");
                }
                return R.ok();
            }
        } catch (Exception e) {
            log.error("登出失败: {}", e.getMessage(), e);
        }
        sysLoginService.logout("", "");
        return R.ok();
    }

    /**
     * 刷新令牌
     *
     * @param request HTTP 请求
     * @return 刷新结果
     */
    @PostMapping("refresh")
    public R<?> refresh(HttpServletRequest request) {
        try {
            CustInfoAppIdLoginVO loginUser = tokenService.getLoginUser(request);
            if (StringUtils.isNotNull(loginUser)) {
                tokenService.refreshToken(loginUser);
                return R.ok();
            }
        } catch (Exception e) {
            log.error("刷新令牌失败: {}", e.getMessage(), e);
        }
        return R.fail("刷新令牌失败");
    }

    /**
     * 用户注册
     *
     * @param registerBody 注册表单
     * @return 注册结果
     */
//    @PostMapping("register")
//    public R<?> register(@RequestBody RegisterBody registerBody) {
//        sysLoginService.register(registerBody);
//        logService.saveRegister(registerBody.getMobile(), "注册", "注册成功", null, "成功");
//        return R.ok();
//    }
}
