package yem.base.common.module.sso;

import com.alibaba.fastjson.JSONObject;
import kd.bos.cache.CacheFactory;
import kd.bos.cache.DistributeSessionlessCache;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.entity.cache.AppCache;
import kd.bos.entity.cache.IAppCache;
import kd.bos.exception.KDException;
import kd.bos.exception.LoginErrorCode;
import kd.bos.logging.Log;
import kd.bos.logging.LogFactory;
import kd.bos.login.thirdauth.ThirdSSOAuthHandler;
import kd.bos.login.thirdauth.UserAuthResult;
import kd.bos.login.thirdauth.UserProperType;
import kd.bos.orm.query.QCP;
import kd.bos.orm.query.QFilter;
import kd.bos.servicehelper.BusinessDataServiceHelper;
import kd.bos.util.StringUtils;
import yem.base.common.utils.HttpHelper;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * 单点登录
 *
 * @description:
 * @date: 2024/5/21
 * @auther: longh
 */
public class SSOLoginPlugin implements ThirdSSOAuthHandler {
    private static final Log log = LogFactory.getLog(SSOLoginPlugin.class);
    private static final String KEY_CACHE_SSOLOGIN = SSOLoginPlugin.class.getName();
    //    private static final String DOMAIN_CONTEXT_URL = UrlService.getDomainContextUrl();
    private static final String DOMAIN_CONTEXT_URL = "http://39.98.69.61:22248/ierp/";
    private static final String MOBILE_CONTEXT_URL = "http://39.98.69.61:22248/ierp/mobile.html?form=yem_prjmob";
    private static final String LOCAL_CONTEXT_URL = "http://127.0.0.1:8080/ierp/login.html";
    private static final String KD_CLOUD_ACCESS_TOKEN = "kdcloudaccesstoken";
    private static final String LOGIN_USER_PHONE = "login_user_realphone";
    private static final String CLIENT_ID = "279140";
    private static final String CLIENT_SECRET = "7466c153ec4eaaa66e723b0847851f0a";
    private static final String USER_PHONE = "18842889815";

    public static String loginOut(boolean mobile) throws Exception {
        long timeStamp = System.currentTimeMillis();
        String redirectUrl = mobile ? MOBILE_CONTEXT_URL : DOMAIN_CONTEXT_URL;
        String signiture = shaEncode(CLIENT_ID + CLIENT_SECRET + timeStamp + redirectUrl);
        String url = String.format("https://api.kingdee.com/auth/oauth2/logout?client_id=%s&signiture=%s&timestamp=%s&redirect_uri=%s", CLIENT_ID, signiture, timeStamp, redirectUrl);
        return url;
    }

    private static String shaEncode(String data) {
        try {
            MessageDigest digest = MessageDigest.getInstance("SHA-1");
            byte[] hash = digest.digest(data.getBytes());
            // 将字节数组转换为十六进制字符串
            StringBuilder hexString = new StringBuilder();
            for (byte b : hash) {
                String hex = Integer.toHexString(0xff & b);
                if (hex.length() == 1) {
                    hexString.append('0');
                }
                hexString.append(hex);
            }
            return hexString.toString();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return data;
    }

    @Override
    public void callTrdSSOLogin(HttpServletRequest request, HttpServletResponse response, String s) {
        try {
            if (localhost(request)) {
                response.sendRedirect(LOCAL_CONTEXT_URL);
                return;
            }
            String redirectUrl = getRedirectUrl(request);
            String url = String.format("https://passport.kingdee.com/passport/oauth2/authorize?client_id=%s&response_type=code&redirect_uri=%s", CLIENT_ID, URLEncoder.encode(redirectUrl, "UTF-8"));
            response.sendRedirect(url);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("单点登录异常", e);
        }
    }

    private boolean localhost(HttpServletRequest request) {
        String requestURL = request.getRequestURL().toString();
        return requestURL.contains("localhost") || requestURL.contains("127.0.0.1");
    }

    @Override
    public UserAuthResult getTrdSSOAuth(HttpServletRequest request, HttpServletResponse response) {
        String code = request.getParameter("code");
        UserAuthResult userAuthResult = new UserAuthResult();
        userAuthResult.setSucess(false);
        if (localhost(request)) return userAuthResult;
        if (StringUtils.isNotEmpty(code)) {
            try {
                // 从云平台获取access_token
                String redirectUrl = getRedirectUrl(request);
                String url = String.format("https://api.kingdee.com/auth/oauth2/access_token?client_id=%s&client_secret=%s&grant_type=authorization_code&redirect_uri=%s&code=%s", CLIENT_ID, CLIENT_SECRET, redirectUrl, code);
                JSONObject responseObj = JSONObject.parseObject(HttpHelper.httpPost(url));
                Integer errCode = responseObj.getInteger("errcode");
                String accessToken;
                if (errCode != null && errCode == 0) {
                    accessToken = responseObj.getJSONObject("data").getString("access_token");
                    request.setAttribute(KD_CLOUD_ACCESS_TOKEN, accessToken);
                } else {
                    String errDesc = StringUtils.isEmpty(responseObj.getString("description")) ? "未获取到access_token信息！" : responseObj.getString("description");
                    userAuthResult.setErrDesc(errDesc);
                    throw new KDException(LoginErrorCode.loginBizException, "系统错误，请联系系统管理员。" + errDesc);
                }
                // 从云平台获取登录用户基本信息
                url = String.format("https://api.kingdee.com/account/user_info?access_token=%s", accessToken);
                JSONObject userInfoObj = JSONObject.parseObject(HttpHelper.httpGet(url));
                errCode = userInfoObj.getInteger("errcode");
                if (errCode != null && errCode == 0) {
                    String phone = userInfoObj.getJSONObject("data").getString("phone");
                    request.setAttribute(LOGIN_USER_PHONE, phone);
                    userAuthResult.setUser(USER_PHONE);
                    userAuthResult.setUserType(UserProperType.Mobile);
                    userAuthResult.setSucess(true);
                } else {
                    String errDesc = StringUtils.isEmpty(userInfoObj.getString("description")) ? "未查询到用户信息！" : userInfoObj.getString("description");
                    throw new KDException(LoginErrorCode.loginBizException, "系统错误，请联系系统管理员。" + errDesc);
                }
            } catch (KDException e) {
                e.printStackTrace();
                log.error("单点登录失败。code：" + code, e);
                throw e;
            } catch (Exception e) {
                e.printStackTrace();
                log.error("单点登录异常", e);
                throw new KDException(e, LoginErrorCode.loginBizException, "系统错误，请联系系统管理员。" + "单点登录异常");
            }
        }
        return userAuthResult;
    }

    private String getRedirectUrl(HttpServletRequest request) {
        String type = request.getParameter("type");
        String requestURI = request.getRequestURI();
        String redirectUrl = DOMAIN_CONTEXT_URL;
        String redirectParam = "";
        if (requestURI.contains("mobile") || "mobile".equals(type)) {
            String formId = request.getParameter("form");
            redirectParam = String.format("?form=%s", StringUtils.isEmpty(formId) ? "yem_prjmob" : formId);
            redirectUrl += "mobile.html";
        }
        return String.format("%s%s", redirectUrl, redirectParam);
    }

    @Override
    public void processSucceedLogin(HttpServletRequest request, String globalSessionId) {
        if (!localhost(request)) {
            // 将从金蝶云平台获取的 access_token 存入分布式缓存, 1天有效期. 后续跳转第三方系统页面时取出使用
            String kdcloudaccesstoken = (String) request.getAttribute(KD_CLOUD_ACCESS_TOKEN);
            String login_user_phone = (String) request.getAttribute(LOGIN_USER_PHONE);
            DistributeSessionlessCache cache = CacheFactory.getCommonCacheFactory().getDistributeSessionlessCache(KEY_CACHE_SSOLOGIN);
            cache.put(globalSessionId, KD_CLOUD_ACCESS_TOKEN, kdcloudaccesstoken, 1 * 24 * 60 * 60);
            cache.put(globalSessionId, LOGIN_USER_PHONE, login_user_phone, 1 * 24 * 60 * 60);
            try {
                QFilter qFilter = new QFilter("phone", QCP.equals, login_user_phone);
                qFilter.and(new QFilter("usertypes.fbasedataid", QCP.equals, 1L));
                DynamicObject user = BusinessDataServiceHelper.loadSingle("bos_user", "id", qFilter.toArray());
                if (user != null) {
                    IAppCache appCache = AppCache.get("yem_rp");
                    appCache.put(globalSessionId, user.getPkValue());
                }
            } catch (Exception e) {
                e.printStackTrace();
                log.error("单点登录异常", e);
            }
        }
        ThirdSSOAuthHandler.super.processSucceedLogin(request, globalSessionId);
    }

}
