package com.kingdee.eas.custom.sso;

import com.alibaba.fastjson.JSON;
import com.kingdee.eas.cp.eip.sso.ltpa.LtpaTokenManager;
import com.kingdee.eas.utils.ExpiringMapCache;
import com.kingdee.shr.base.syssetting.exception.SHRWebException;
import com.kingdee.util.StringUtils;
import org.apache.log4j.Logger;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.*;

/**
 * @Description OA单点sHR
 * @Date 2024/10/30 11:22
 * @Created by Heyuan
 */
public class OAToSHR extends HttpServlet {
    private static Logger logger = Logger.getLogger(OAToSHR.class);
    private static ExpiringMapCache<String, String> redirectUrlCache = new ExpiringMapCache<>();
    private Properties prop = new Properties();
    private String propPath = System.getProperty("EAS_HOME") + "/server/properties/scy/OASSOConfig.properties";

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        logger.error("OAToSHR -> doGet");
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        logger.error("OAToSHR -> doPost");
        BufferedReader streamReader = null;
        String resultStr = null;
        prop.load(new FileInputStream(propPath));
        logger.error("OAToSHR  requestUrl" + req.getRequestURL().toString());
        try {
            String ticket = req.getParameter("ticket");
            logger.error("接收到的请求参数是：ticket " + ticket);
            if (StringUtils.isEmpty(ticket)) {
                //认证
                authorize(req, resp);
            } else {
                //获取用户信息
                callBack(req, resp, ticket);
            }
        } catch (Exception e) {
            e.printStackTrace();
            Map result = new HashMap();
            result.put("msgType", "0");
            result.put("reason", e.getMessage());
            resultStr = JSON.toJSONString(result);
            resp.setStatus(500);
            PrintWriter writer = resp.getWriter();
            resp.setContentType("application/json");
            writer.write(resultStr);
            writer.close();
        } finally {
            try {
                if (streamReader != null) {
                    streamReader.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 认证
     * 拼接OA认证接口地址，转发
     *
     * @param resp
     * @throws Exception
     */
    public void authorize(HttpServletRequest req, HttpServletResponse resp) throws Exception {
        String authorizePath = prop.getProperty("authorizePath");
        if (StringUtils.isEmpty(authorizePath)) {
            throw new RuntimeException("authorizePath不能为空! 请检查配置文件: " + propPath);
        }
        String response_type = prop.getProperty("response_type");
        if (StringUtils.isEmpty(response_type)) {
            throw new RuntimeException("response_type不能为空! 请检查配置文件: " + propPath);
        }
        String client_id = prop.getProperty("client_id");
        if (StringUtils.isEmpty(client_id)) {
            throw new RuntimeException("client_id不能为空! 请检查配置文件: " + propPath);
        }
        String redirect_uri1 = prop.getProperty("redirect_uri1");
        if (StringUtils.isEmpty(redirect_uri1)) {
            throw new RuntimeException("redirect_uri1不能为空! 请检查配置文件: " + propPath);
        }
        String redirectUrl = req.getParameter("redirect");
        if (StringUtils.isEmpty(redirectUrl)) {
            String serverName = prop.getProperty("serverName");
            if (StringUtils.isEmpty(serverName)) {
                throw new RuntimeException("serverName不能为空! 请检查配置文件: " + propPath);
            }
            redirectUrl = serverName + "/shr/dynamic.do?uipk=shr.perself.homepage";
        }
        Random random = new Random();
        String key = System.currentTimeMillis() + String.valueOf(random.nextInt(99999));
        redirectUrlCache.put(key, redirectUrl, 300000);
        logger.error("callBack redirectUrl" + redirectUrl);
        redirect_uri1 += "?redirect=" + key;
        Map params = new HashMap();
        params.put("client_id", client_id);
        params.put("response_type", response_type);
        params.put("redirect_uri", URLEncoder.encode(redirect_uri1, "UTF-8"));
        String urlString = SsoUtil.appendUrl(authorizePath, params);
        resp.sendRedirect(urlString);
        logger.error("authorize url" + urlString);
    }

    /**
     * OA回调方法
     * 获取Token和用户信息，单点到shr
     *
     * @param req
     * @param resp
     * @param ticket
     * @throws SHRWebException
     * @throws UnsupportedEncodingException
     */
    public void callBack(HttpServletRequest req, HttpServletResponse resp, String ticket) throws
            SHRWebException, UnsupportedEncodingException {
        logger.error("callback方法入参");
        if (StringUtils.isEmpty(ticket)) {
            throw new RuntimeException("ticket不能为空!");
        }
        String getAccessTokenPath = prop.getProperty("getAccessTokenPath");
        if (StringUtils.isEmpty(getAccessTokenPath)) {
            throw new RuntimeException("getAccessTokenPath不能为空! 请检查配置文件: " + propPath);
        }
        String client_secret = prop.getProperty("client_secret");
        if (StringUtils.isEmpty(client_secret)) {
            throw new RuntimeException("client_secret不能为空! 请检查配置文件: " + propPath);
        }
        String client_id = prop.getProperty("client_id");
        if (StringUtils.isEmpty(client_id)) {
            throw new RuntimeException("client_id不能为空! 请检查配置文件: " + propPath);
        }
        String redirect_uri2 = prop.getProperty("redirect_uri2");
        if (StringUtils.isEmpty(redirect_uri2)) {
            throw new RuntimeException("redirect_uri2不能为空! 请检查配置文件: " + propPath);
        }
        String getLoginIdPath = prop.getProperty("getLoginIdPath");
        if (StringUtils.isEmpty(getLoginIdPath)) {
            throw new RuntimeException("getLoginIdPath不能为空! 请检查配置文件: " + propPath);
        }
        String redirectUrl = req.getParameter("redirect");
        logger.error("callBack redirectUrl" + redirectUrl);
        Map params = new HashMap();
        params.put("client_id", client_id);
        params.put("client_secret", client_secret);
        params.put("grant_type", "authorization_code");
        params.put("code", ticket);
        params.put("redirect_uri", URLEncoder.encode(redirect_uri2, "UTF-8"));
        try {
            String token = SsoUtil.getAccessToken(getAccessTokenPath, params);
            logger.error(token);
            //从人员对象，获取纷享用户userId
            String loginId = SsoUtil.loginId2userId(getLoginIdPath, token);
            String loginUrl = login(loginId, redirectUrl);
            resp.sendRedirect(loginUrl);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
    }

    /**
     * 获取携带账号和密码的登录地址
     *
     * @param userNumber
     * @param redirectUrlKey
     * @return
     */
    private String login(String userNumber, String redirectUrlKey) throws Exception {
        String password = LtpaTokenManager.generate(userNumber, LtpaTokenManager.getDefaultLtpaConfig()).toString();
        logger.error("login: password" + password);
        String serverName = prop.getProperty("serverName");
        if (StringUtils.isEmpty(serverName)) {
            throw new RuntimeException("serverName不能为空! 请检查配置文件: " + propPath);
        }
        StringBuilder url = new StringBuilder();
        url.append("/shr/index2sso.jsp?username=").append(userNumber)
                .append("&password=").append(password).append("&redirectTo=");
        StringBuilder redirectUrlStr = new StringBuilder();
        if (StringUtils.isEmpty(redirectUrlKey)) {
            redirectUrlStr.append(serverName).append("/shr/dynamic.do?uipk=shr.perself.homepage");
        } else {
            String redirectUrl = redirectUrlCache.get(redirectUrlKey);
            if (redirectUrl.contains(serverName)) {
                redirectUrlStr.append(redirectUrl);
            } else {
                redirectUrlStr.append(serverName).append(redirectUrl);
            }
        }
        //todo
        //校验流程生效状态
        //String redirect = SsoUtil.checkFlowEffectiveStateForPc(redirectUrlStr.toString(), serverName);
        String redirect = SsoUtil.checkBillExistForPc(redirectUrlStr.toString(), serverName);
        String encode = URLEncoder.encode(redirect, "UTF-8");
        url.append(URLEncoder.encode(encode, "UTF-8"));
        logger.error("login: url" + url);
        return url.toString();
    }
}
