package com.hotent.auth.server.service.impl;

import cn.hutool.crypto.digest.MD5;
import com.hotent.Feign.UCFeignClient;
import com.hotent.auth.server.service.AuthenticationThirdPartyService;
import com.hotent.base.conf.JwtConfig;
import com.hotent.base.conf.SsoConfig;
import com.hotent.base.exception.BaseException;
import com.hotent.base.exception.CertificateException;
import com.hotent.base.feign.PortalFeignService;
import com.hotent.base.jwt.JwtAuthenticationRequest;
import com.hotent.base.jwt.JwtTokenHandler;
import com.hotent.base.model.CommonResult;
import com.hotent.base.util.CacheEvictUtil;
import com.hotent.base.util.RSAUtil;
import com.hotent.base.util.StringUtil;
import com.hotent.uc.api.model.IUser;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * 用户认证 服务实现类
 *
 * @author liangjc
 * @company 广州宏天软件股份有限公司
 * @email liangjc@jee-soft.cn
 * @date 2023-09-18 17:29
 */
@Service
public class AuthenticationThirdPartServiceImpl implements AuthenticationThirdPartyService {
    private static final Logger logger = LoggerFactory.getLogger(AuthenticationThirdPartServiceImpl.class);
    private static final String splitStr = "@@@###@@@";
    @Resource
    AuthenticationManager authenticationManager;
    @Resource
    UserDetailsService userDetailsService;
    @Resource
    JwtTokenHandler jwtTokenHandler;
    @Resource
    UCFeignClient ucFeignClient;
    @Resource
    SsoConfig ssoConfig;
    @Value("${system.mode.demo:false}")
    protected boolean demoMode;
    @Resource
    PortalFeignService portalFeignService;
    @Resource
    JwtConfig jwtConfig;
    @Value("${qzSetting.isHiddenDem:false}")
    protected boolean isHiddenDem; //是否隐藏维度信息

    /**
     * 删除缓存的用户详情
     * <p>该方法没有方法体，通过注解在切面中删除缓存数据</p>
     *
     * @param userAccount
     */
    private void deleteUserDetailsCache(String userAccount) {
        CacheEvictUtil.deleteUserDetailsCache(userAccount);
    }

    @Override
    public CommonResult<?> createAuthenticationTokenCode(JwtAuthenticationRequest authenticationRequest) {
        String clientId = authenticationRequest.getClientId();
        if (StringUtils.isBlank(authenticationRequest.getClientId())) {
            throw new BaseException("客户端ID不能为空");
        }
        String randImageId = authenticationRequest.getRandImageId();
        String randImageCode = authenticationRequest.getRandImageCode();
        if (StringUtils.isBlank(randImageId) || StringUtils.isBlank(randImageCode)){
            throw new BaseException("验证码不能为空");
        }
        if (!checkCaptchaCode(randImageId, randImageCode)){
            throw new BaseException("验证码校验失败");
        }
        CommonResult result = portalFeignService.getPortalBizSystemUrlBySysCode(clientId);
        String redirectUrl = null;
        if (result != null && result.getCode() == 200 && result.getValue() != null) {
            redirectUrl = (String) result.getValue();
        }
        if (StringUtils.isBlank(redirectUrl)) {
            throw new BaseException("未配置登录地址，请联系管理员");
        }
        logger.info("登录方式:【用户名密码】，校验clientId成功 clientId:{} redirectUrl:{}", clientId,redirectUrl);
        String reqAccount = authenticationRequest.getUsername();
        String reqPassword = "";
        try {
            //密码rsa解密
            reqPassword = RSAUtil.Decrypt(authenticationRequest.getPassword());
        } catch (Exception e) {
            throw new RuntimeException("解密密码异常，请检查RSA公钥和私钥配置");
        }
        //清除用户缓存
        this.deleteUserDetailsCache(reqAccount);
        try {
            authenticate(reqAccount, reqPassword);
        } catch (Exception e) {
            logger.error(String.format("Login failed account[%s].", reqAccount), e);
            throw new BaseException("用户名或密码错误");
        }
        String shortCode = MD5.create().digestHex("code_login:" + reqAccount + "_" + System.currentTimeMillis()).substring(0, 4);
        logger.info("登录方式:【用户名密码】，创建code成功 参数：account:{} code:{}", reqAccount,shortCode);
        jwtTokenHandler.addShortCache(shortCode, reqAccount + "@@@###@@@" + reqPassword);
        Map<String, String> map = new HashMap<>();
        map.put("code", shortCode);
        map.put("url", redirectUrl);
        return new CommonResult<>(true, "获取shortCode成功！", map);
    }

    @Override
    public CommonResult<?> generateShortAuthenticationToken(HttpServletRequest request) {
        String authToken = request.getHeader(jwtConfig.getHeader());
        if (StringUtil.isEmpty(authToken) || authToken.length() < 8) {
            return new CommonResult<String>(false, "未登录！");
        }
        final String token = authToken.substring(7);
        if (StringUtil.isEmpty(token)) {
            return new CommonResult<String>(false, "未登录！token为空！");
        }

        MD5 md5Uitls = new MD5();
        String account = jwtTokenHandler.getUsernameFromToken(token);
        String userInfo = jwtTokenHandler.getUserDetailCache(account);
        if (StringUtils.isBlank(userInfo)) {
            final UserDetails userDetails = userDetailsService.loadUserByUsername(account);
            String userName = userDetails.getUsername();
            String mobile = "";
            if (userDetails instanceof IUser) {
                IUser user = ((IUser) userDetails);
                userName = user.getFullname();
                mobile = user.getMobile();
            }
            userInfo = account + splitStr + userName + splitStr + mobile;
            jwtTokenHandler.addUserDetailCache(account, userInfo);
        }
        String shortCode = md5Uitls.digestHex("code:" + token + "_" + System.currentTimeMillis()).substring(0, 4);
        logger.info("debug==>小程序 code【生成】   accountId：【" + account + "】  code:" + shortCode);
        jwtTokenHandler.addShortCache(shortCode, token + splitStr + userInfo);
        return new CommonResult<String>(true, "获取shortCode成功！", shortCode);
    }

    @Override
    public CommonResult<?> convertShortAuthenticationToken(String shortCode) {
        String tokenAccount = jwtTokenHandler.getShortCache(shortCode);
        if (StringUtil.isEmpty(tokenAccount)) {
            return new CommonResult<String>(false, "shortCode:" + shortCode + "换取token失败！");
        }
        jwtTokenHandler.removeShortCache(shortCode);
        String[] split = tokenAccount.split(splitStr);
        Map<String, String> result = new HashMap<>();
        if (split.length > 3) {
            String token = split[0];
            String account = split[1];
            String userName = split[2];
            String mobile = split[3];
            result.put("token", token);
            result.put("account", account);
            result.put("fullName", userName);
            result.put("mobile", mobile);
        }

        return new CommonResult<>(true, "换取token成功", result);
    }

    @Override
    public void saveCaptchaCode(String codeId, String code) {
        jwtTokenHandler.addCaptchaCache(codeId, code);
    }

    public boolean checkCaptchaCode(String codeId, String requestCode) {
        String captchaCache = jwtTokenHandler.getCaptchaCache(codeId);
        if (StringUtil.isNotEmpty(captchaCache) && captchaCache.equals(requestCode)) {
            jwtTokenHandler.removeCaptchaCache(codeId);
            return true;
        }
        return false;
    }


    @Override
    public ResponseEntity<?> createAuthenticationTokenDevelop(JwtAuthenticationRequest authenticationRequest) {
        String reqAccount = authenticationRequest.getUsername();
        String reqPassword = authenticationRequest.getPassword();

//        try {
////            String qwer1234 = RSAUtil.publicEncrypt("qwer1234", RSAUtil.getPublicKey(RSAUtil.publicKey));
////            System.out.println("micorservice debug qwer1234==>"+qwer1234);
////            reqPassword = RSAUtil.Decrypt(authenticationRequest.getPassword());
//        }catch (Exception e){
//
//            throw new RuntimeException("解密密码异常，请检查RSA公钥和私钥配置");
//        }
        com.hotent.entity.CommonResult apiToken = ucFeignClient.getApiToken(reqAccount, reqPassword, null);
        return ResponseEntity.ok(apiToken);

    }

    private void authenticate(String username, String password) throws AuthenticationException, CertificateException {
        Objects.requireNonNull(username);
        Objects.requireNonNull(password);
        authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
    }

}
