package com.shr.api;

import com.kingdee.shr.api.Response;
import com.kingdee.shr.api.SHRClient;
import com.kingdee.shr.api.Token;
import com.kingdee.shr.sso.client.ltpa.LtpaTokenManager;
import com.kingdee.shr.sso.client.util.UrlUtil;
import com.shr.exception.ShrException;
import com.shr.utils.JsonUtil;
import org.apache.commons.httpclient.Cookie;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.methods.GetMethod;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * @author Inori
 */
@Component
public class CallShrOsfApi {

    private static final Logger log = LoggerFactory.getLogger(CallShrOsfApi.class);

    private String serverUrl;

    public CallShrOsfApi() {
        serverUrl = "http://172.16.1.67:6890/shr";
    }

    public Response callShrOsf(String serviceName, Map<String, Object> param) {
        SHRClient shrClient = new SHRClient();
        try {
            Token token = this.loginShrByUser(serverUrl);
            Response response = shrClient.executeOSFService(serverUrl, token, serviceName, param);
            log.info("SHR返回结果: {}", JsonUtil.toString(response.getData()));
            return response;
        } catch (IOException e) {
            e.printStackTrace();
            throw new ShrException("SHR返回异常: " + e.getMessage());
        }
    }

    public Token loginShrByUser(String serverUrl) throws IOException {
        String loginUrl = serverUrl + "/OTP2sso.jsp";
        Map<String, Object> parameters = new HashMap<>(10);
        parameters.put("username", "0196");
        String password = LtpaTokenManager.generate((String) parameters.get("username"), LtpaTokenManager.getDefaultLtpaConfig(), "OTP").toString();
        parameters.put("password", password);
        parameters.put("userAuthPattern", "OTP");
        parameters.put("isNotCheckRelogin", "true");
        String url = UrlUtil.assembleUrl(loginUrl, parameters);
        HttpClient client = new HttpClient();
        client.getParams().setParameter("http.protocol.allow-circular-redirects", true);
        GetMethod method = new GetMethod(url);
        method.addRequestHeader("Referer", serverUrl);
        method.getParams().setParameter("http.protocol.single-cookie-header", true);
        method.getParams().setParameter("http.protocol.cookie-policy", "compatibility");
        method.setFollowRedirects(true);
        int status = client.executeMethod(method);
        Token token;
        if (status != 200) {
            System.err.println("Method failed: " + method.getStatusLine());
            throw new HttpException("login shr fail, status: " + status);
        } else {
            token = this.getToken(client.getState().getCookies());
            return token;
        }
    }

    private Token getToken(Cookie[] cookies) throws HttpException {
        Cookie cookie;

        for (Cookie value : cookies) {
            cookie = value;
            if ("JSESSIONID".equalsIgnoreCase(cookie.getName()) && !cookie.getPath().contains("sso")) {
                Token token = new Token();
                token.setDomain(cookie.getDomain());
                token.setPath(cookie.getPath());
                token.setValue(cookie.getValue());
                return token;
            }
        }

        throw new HttpException("getToken fail, cookies: " + this.cookieToString(cookies));
    }

    private String cookieToString(Cookie[] cookies) {
        Cookie cookie;
        StringBuilder sb = new StringBuilder();

        for (int i = 0; i < cookies.length; ++i) {
            cookie = cookies[i];
            if (i != 0) {
                sb.append(",");
            }

            sb.append("[name=");
            sb.append(cookie.getName());
            sb.append(", path=");
            sb.append(cookie.getPath());
            sb.append(", value=");
            sb.append(cookie.getValue());
            sb.append("]");
        }

        return sb.toString();
    }


}
