package com.bcxin.tenant.domain.services.impls;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.bcxin.Infrastructures.enums.AbnormalPersonnelEmployeeType;
import com.bcxin.Infrastructures.enums.CredentialType;
import com.bcxin.Infrastructures.enums.OccupationType;
import com.bcxin.Infrastructures.utils.AuthUtil;
import com.bcxin.Infrastructures.utils.RedisUtil;
import com.bcxin.tenant.domain.configs.SSOConfig;
import com.bcxin.tenant.domain.dto.SingleLoginUserDto;
import com.bcxin.tenant.domain.entities.EmployeeEntity;
import com.bcxin.tenant.domain.repositories.EmployeeRepository;
import com.bcxin.tenant.domain.services.EmployeeService;
import com.bcxin.tenant.domain.services.NaturalSingleLoginService;
import com.bcxin.tenant.domain.services.commands.CreateEmployeeRequestCommand;
import com.bcxin.tenant.domain.utils.SSOContants;
import com.bjtoon.uia.sdk.UiaConstants;
import com.bjtoon.uia.sdk.client.DefaultUiaClient;
import com.bjtoon.uia.sdk.client.UiaClient;
import com.bjtoon.uia.sdk.domain.AccessTokenVo;
import com.bjtoon.uia.sdk.domain.UserInfoVo;
import com.bjtoon.uia.sdk.exception.UiaException;
import com.bjtoon.uia.sdk.request.UiaOauthAccessTokenRequest;
import com.bjtoon.uia.sdk.request.UiaOauthUserInfoRequest;
import com.bjtoon.uia.sdk.response.UiaOauthAccessTokenResponse;
import com.bjtoon.uia.sdk.response.UiaOauthUserInfoResponse;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author linqinglin
 * @date 2021/10/13 0013 9:47
 */
@Service
public class NaturalSingleLoginServiceImpl implements NaturalSingleLoginService {

    private final Logger logger = LoggerFactory.getLogger(NaturalSingleLoginServiceImpl.class);

    private final EmployeeRepository employeeRepository;

    private final EmployeeService employeeService;

    private final RedisUtil redisUtil;

    public NaturalSingleLoginServiceImpl(EmployeeRepository employeeRepository,
                                         EmployeeService employeeService,
                                         RedisUtil redisUtil){
        this.employeeRepository = employeeRepository;
        this.employeeService = employeeService;
        this.redisUtil = redisUtil;
    }

    /**
     * 单点登录 创建更新用户
     * @param code
     * @throws Exception
     */
    @Override
    public SingleLoginUserDto saveLoginUser(String code){
        String token = getToken(code);
        if(StrUtil.isNotEmpty(token)){
            //核心请求客户端，构建后可复用
            UiaClient uiaClient = new DefaultUiaClient(SSOConfig.getUrl());

            UiaOauthUserInfoRequest uiaOauthUserInfoRequest = new UiaOauthUserInfoRequest(SSOContants.GET_USERINFO,token,SSOConfig.getClientSecret());
            //解密返回的身份证号
            UiaOauthUserInfoResponse userInfoResponse = uiaClient.execute(uiaOauthUserInfoRequest, true);
            if (null != userInfoResponse && userInfoResponse.isSuccess()) {
                UserInfoVo userInfoVo = userInfoResponse.getUserInfoVo();
                //获取到用户之后
                EmployeeEntity employee = employeeRepository.getByIdNum(SSOConfig.getDomainId(), userInfoVo.getCertNo());

                String employeeId = null;
                List<String> roles = null;
                if(employee == null){
                    String password = null;
                    if(StrUtil.isNotEmpty(userInfoVo.getCertNo())){
                        String certNo = userInfoVo.getCertNo();
                        password = StrUtil.isNotEmpty(SSOConfig.getPassPrefix())? SSOConfig.getPassPrefix()+certNo.substring(certNo.length()-6,certNo.length()):null;
                    }
                    employeeId = this.employeeService.dispatch(
                            CreateEmployeeRequestCommand.create(SSOConfig.getDomainId(),
                                    userInfoVo.getCertName(), userInfoVo.getMobile(),
                                    password,
                                    SSOConfig.getDepartId(), OccupationType.Normal, null,
                                    new Date(), CredentialType.IdCard,
                                    userInfoVo.getCertNo(),
                                    AuthUtil.getCurrentOperator(),
                                    AbnormalPersonnelEmployeeType.NOT_VERIFY));
                    roles = new ArrayList<>();
                    roles.add(SSOConfig.getRoleId());
                }else{
                    employeeId = employee.getId();
                }
                return SingleLoginUserDto.create(employeeId,userInfoVo.getCertNo(),roles);
            }else if(null != userInfoResponse){
                logger.error(JSON.toJSONString(userInfoResponse));
            }
        }

        return null;
    }

    private String getToken(String code){
        String token = null;
        if(redisUtil.get(code) != null){
            token = redisUtil.get(code).toString();
        }else{
            //核心请求客户端，构建后可复用
            UiaClient uiaClient = new DefaultUiaClient(SSOConfig.getUrl());
            try {
                //获取 access_token
                UiaOauthAccessTokenRequest request =
                        new UiaOauthAccessTokenRequest(SSOContants.GET_TOKEN,SSOConfig.getClientId(),SSOConfig.getClientSecret(),code, UiaConstants.GRANT_TYPE_CODE, UiaConstants.SCOPE_USER_INFO);
                UiaOauthAccessTokenResponse tokenResponse = uiaClient.execute(request);

                if (tokenResponse.isSuccess()) {
                    //调用成功
                    AccessTokenVo accessTokenVo=tokenResponse.getAccessTokenVo();
                    token = accessTokenVo.getAccess_token();
                    redisUtil.set(code,token,24*60*60);
                }else {
                    logger.error(JSON.toJSONString(tokenResponse));
                }
            } catch (UiaException e) {
                logger.error(e.getMessage(), e);
                throw e;
            }
        }
        return token;
    }

    /**
     * 通用单点登录 创建更新用户
     * @param certName
     * @param certNo
     * @param mobile
     * @throws Exception
     */
    @Override
    public SingleLoginUserDto saveCommonLoginUser(String certName,String certNo,String mobile){
        if(StrUtil.isNotEmpty(certNo)){
            //获取到用户之后
            EmployeeEntity employee = employeeRepository.getByIdNum(SSOConfig.getDomainId(), certNo);

            String employeeId = null;
            List<String> roles = null;
            if(employee == null){
                String password = StrUtil.isNotEmpty(SSOConfig.getPassPrefix())? SSOConfig.getPassPrefix()+certNo.substring(certNo.length()-6,certNo.length()):null;
                employeeId = this.employeeService.dispatch(
                        CreateEmployeeRequestCommand.create(SSOConfig.getDomainId(),
                                certName, mobile,
                                password,
                                SSOConfig.getDepartId(), OccupationType.Normal, null,
                                new Date(), CredentialType.IdCard,
                                certNo,
                                AuthUtil.getCurrentOperator(),
                                AbnormalPersonnelEmployeeType.NOT_VERIFY));
                roles = new ArrayList<>();
                roles.add(SSOConfig.getRoleId());
            }else{
                employeeId = employee.getId();
            }
            return SingleLoginUserDto.create(employeeId,certNo,roles);
        }

        return null;
    }

    /**
     * 单点登录 法人创建更新用户
     * @param certName
     * @param certNo
     * @param mobile
     * @throws Exception
     */
    @Override
    public SingleLoginUserDto saveLegalLoginUser(String certName,String certNo,String mobile){
        if(StrUtil.isNotEmpty(certNo)){
            //获取到用户之后
            EmployeeEntity employee = employeeRepository.getByIdNum(SSOConfig.getDomainId(), certNo);

            List<String> roles = null;
            if(employee == null){
                String password = StrUtil.isNotEmpty(SSOConfig.getPassPrefix())? SSOConfig.getPassPrefix()+certNo.substring(certNo.length()-6,certNo.length()):null;
                this.employeeService.dispatch(
                        CreateEmployeeRequestCommand.create(SSOConfig.getDomainId(),
                                certName, mobile,
                                password,
                                SSOConfig.getDepartId(), OccupationType.Normal, null,
                                new Date(), CredentialType.IdCard,
                                certNo,
                                AuthUtil.getCurrentOperator(),
                                AbnormalPersonnelEmployeeType.NOT_VERIFY));
                employee = employeeRepository.getByIdNum(SSOConfig.getDomainId(), certNo);
                roles = new ArrayList<>();
                roles.add(SSOConfig.getLegalRoleId());
            }
            return SingleLoginUserDto.create(employee.getId(),certNo,roles);
        }

        return null;
    }

}
