package com.kingdee.eas.custom.perfweb.utils;

import com.kingdee.eas.custom.integration.base.config.AppConfig;
import com.kingdee.eas.custom.integration.base.config.SpringContextHolder;
import com.kingdee.eas.custom.integration.base.service.AppConfigService;
import com.kingdee.eas.custom.integration.base.service.StateValidator;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.web.util.UriComponentsBuilder;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

/**
 *类名称: UrlParamUtil
 *功能描述: 飞书待办跳转地址工具类
 *负责拼接并编码 pcurl / appurl 参数，集中管理域名、入口路径和各业务页面路径
 *创建日期: 2026-06-12
 *作    者: 青梧
 *版    本: 1.0
 */
public class UrlParamUtil {

    private static final Logger logger = Logger.getLogger(UrlParamUtil.class);

    /** integration 飞书单点入口（相对 SHR 域名） */
    private static final String FEISHU_AUTH_PATH = "/qy/auth/feishu";

    //===== 基础域名（切换环境时改 BASE_HOST / SHR_HOST 等当前生效变量）=====
    /** OA 跳转网关前缀 - 正式环境（oAToSHR） */
    public static String BASE_HOST_PROD = "http://ehr.shichuangyi.cn:8080/shr/api/oAToSHR?redirect=";
    /** OA 跳转网关前缀 - 测试环境（oAToSHR） */
    public static String BASE_HOST_TEST = "http://10.0.3.24:8080/shr/api/oAToSHR?redirect=";
    /** 当前生效的 OA 待办网关 */
    public static String BASE_HOST = BASE_HOST_PROD;
    /** SHR 系统地址 - 正式环境 */
    public static String SHR_HOST_PROD = "http://ehr.shichuangyi.cn:8080";
    /** SHR 系统地址 - 测试环境 */
    public static String SHR_HOST_TEST = "http://10.0.3.24:8080";
    /** 当前生效的 SHR 地址（dynamic.do 等业务页） */
    public static String SHR_HOST = SHR_HOST_PROD;
    //正式环境
    public static String PRODURL = "https://freport.shichuangyi.cn/oa-ofs/prod-api/approve/rest/ofs/ReceiveRequestInfoByJson";
    //测试环境
    public static String TESTURL = "https://mtest.shichuangyi.cn/prod-approval-api/approve/rest/ofs/ReceiveRequestInfoByJson";
    //绩效工作台 - 正式环境
    public static String JXGZT_PC_PROD = "http://ehr.shichuangyi.cn:8080/shr/dynamic.do?inFrame=true&fromHeader=true&uipk=com.kingdee.shr.perfweb.app.perfportal.core&serviceId=fUjSqQK1RouZaEJUI2jH5vI9KRA%3D";
    public static String JXGZT_BOS_PROD = "http://ehr.shichuangyi.cn:8080/shr/dynamic.do?inFrame=true&fromHeader=true&uipk=com.kingdee.shr.perfweb.app.perfportal.core&serviceId=fUjSqQK1RouZaEJUI2jH5vI9KRA%3D";
    //绩效工作台 - 测试环境
    public static String JXGZT_PC_TEST = "http://10.0.3.24:8080/shr/dynamic.do?inFrame=true&fromHeader=true&uipk=com.kingdee.shr.perfweb.app.perfportal.core&serviceId=fUjSqQK1RouZaEJUI2jH5vI9KRA%3D";
    public static String JXGZT_BOS_TEST = "http://10.0.3.24:8080/shr/dynamic.do?inFrame=true&fromHeader=true&uipk=com.kingdee.shr.perfweb.app.perfportal.core&serviceId=fUjSqQK1RouZaEJUI2jH5vI9KRA%3D";
    public static String JXGZT_PC = JXGZT_PC_PROD;
    public static String JXGZT_BOS = JXGZT_BOS_PROD;
    //默认组织ID（考核结果汇总列表 hrOrgId）
    public static String DEFAULT_HR_ORG_ID = "00000000-0000-0000-0000-000000000000CCE7AED4";

    /**
     *考核结果汇总列表页 query 模板。
     *动态参数使用 {@code {period}}、{@code {perfPlanId}}、{@code {hrOrgId}} 占位，拼接时需对值做 URL 编码。
     */
    private static final String EVA_RESULT_MANAGER_LIST_QUERY =
            "uipk=com.kingdee.shr.perfweb.app.base.evalplan.evaResultManager.list"
                    + "&serviceId=nQafn+gKQ+CngP3xudsk5PI9KRA="
                    + "&isOrg=0"
                    + "&period={period}"
                    + "&perfPlanId={perfPlanId}"
                    + "&hrOrgId={hrOrgId}";

    /**
     * 绩效考核结果报表列表页 query 模板（飞书待办跳转）。
     * periodId 为对应待办的考核周期 ID。
     */
    private static final String CENTER_PERF_STAT_REPORT_LIST_QUERY =
            "uipk=com.kingdee.eas.custom.perfweb.handler.CenterPerfStatReport.list"
                    + "&serviceId=eF6u2TdvSbScepkXUeRU1vI9KRA%3D"
                    + "&inFrame=true"
                    + "&periodId={periodId}";

    private static final String DEFAULT_CHARSET = "UTF-8";

    /**
     *对字符串进行 URL 编码（UTF-8），用于 query 参数值。
     *例如：{@code urlEncode("a=b")} 返回 {@code "a%3Db"}
     *
     *@param value 待编码字符串，null 或空串返回空串
     *@return 编码后的字符串
     */
    public static String urlEncode(String value) {
        if (value == null || value.isEmpty()) {
            return "";
        }
        try {
            return URLEncoder.encode(value, DEFAULT_CHARSET);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("URL encode failed: " + value, e);
        }
    }

    /**
     *替换模板中的 {@code {key}} 占位符。
     *
     *@param template 含占位符的模板，如 {@code "...&period={period}&perfPlanId={perfPlanId}"}
     *@param params   key 对应占位符名称（不含花括号），value 为替换值（调用方自行决定是否已编码）
     *@return 替换后的字符串
     */
    public static String fillUrlTemplate(String template, Map<String, String> params) {
        if (template == null) {
            return null;
        }
        if (params == null || params.isEmpty()) {
            return template;
        }
        String result = template;
        for (Map.Entry<String, String> entry : params.entrySet()) {
            String replacement = entry.getValue() != null ? entry.getValue() : "";
            result = result.replace("{" + entry.getKey() + "}", replacement);
        }
        return result;
    }

    /**
     *替换模板占位符，并对每个参数值自动做 URL 编码（传入 BOS 原始 ID 即可）。
     */
    public static String fillUrlTemplateEncoded(String template, Map<String, String> rawParams) {
        Map<String, String> encodedParams = new HashMap<>();
        if (rawParams != null) {
            for (Map.Entry<String, String> entry : rawParams.entrySet()) {
                encodedParams.put(entry.getKey(), urlEncode(entry.getValue()));
            }
        }
        return fillUrlTemplate(template, encodedParams);
    }

    /**
     *构建考核结果汇总列表页地址（dynamic.do）。
     *
     *@param periodId    考核周期 ID（summaryInfo.getPeriod().getId()）
     *@param perfPlanId  考核方案 ID（summaryInfo.getEvaPlan().getId()）
     *@param hrOrgId     组织 ID，为空时使用 {@link #DEFAULT_HR_ORG_ID}
     *@return 完整 SHR 页面 URL，未套 OA redirect
     */
    public static String buildEvaResultManagerListUrl(String periodId, String perfPlanId, String hrOrgId) {
        Map<String, String> params = new HashMap<>();
        params.put("period", periodId);
        params.put("perfPlanId", perfPlanId);
        params.put("hrOrgId", resolveHrOrgId(hrOrgId));
        String query = fillUrlTemplateEncoded(EVA_RESULT_MANAGER_LIST_QUERY, params);
        return SHR_HOST + "/shr/dynamic.do?" + query;
    }

    /**
     *构建考核结果汇总列表页地址，hrOrgId 使用 {@link #DEFAULT_HR_ORG_ID}。
     */
    public static String buildEvaResultManagerListUrl(String periodId, String perfPlanId) {
        return buildEvaResultManagerListUrl(periodId, perfPlanId, DEFAULT_HR_ORG_ID);
    }

    /**
     * 构建考核结果汇总列表页的 OA 待办跳转地址（oAToSHR，非 Bot 消息）。
     */
    public static String buildEvaResultManagerListOaUrl(String periodId, String perfPlanId) {
        return buildOaRedirectUrl(buildEvaResultManagerListUrl(periodId, perfPlanId));
    }

    /**
     * 构建考核结果汇总列表页的 OA 待办跳转地址（oAToSHR，非 Bot 消息）。
     */
    public static String buildEvaResultManagerListOaUrl(String periodId, String perfPlanId, String hrOrgId) {
        return buildOaRedirectUrl(buildEvaResultManagerListUrl(periodId, perfPlanId, hrOrgId));
    }

    /**
     * 构建绩效考核结果报表列表页地址（dynamic.do）。
     *
     * @param periodId 考核周期 ID
     */
    public static String buildCenterPerfStatReportListUrl(String periodId) {
        Map<String, String> params = new HashMap<>();
        params.put("periodId", periodId != null ? periodId : "");
        String query = fillUrlTemplateEncoded(CENTER_PERF_STAT_REPORT_LIST_QUERY, params);
        return SHR_HOST + "/shr/dynamic.do?" + query;
    }

    /**
     * 构建绩效考核结果报表列表页的 OA 待办跳转地址（oAToSHR，非 Bot 消息）。
     */
    public static String buildCenterPerfStatReportListOaUrl(String periodId) {
        return buildOaRedirectUrl(buildCenterPerfStatReportListUrl(periodId));
    }

    /**
     * 绩效工作台 Bot 消息跳转地址（integration 单点 + 目标页）。
     * 用于：启动考核、单人/批量评分、考核结果公示。
     */
    public static String buildPerfPortalFeishuMessageUrl() {
        return buildFeishuMessageUrl(JXGZT_PC);
    }

    /**
     * @deprecated 待办请用 {@link #buildOaRedirectUrl(String)}；Bot 消息请用 {@link #buildPerfPortalFeishuMessageUrl()}
     */
    public static String buildPerfPortalOaUrl() {
        return buildPerfPortalFeishuMessageUrl();
    }

    /**
     * Bot 消息跳转地址：integration {@code /qy/auth/feishu?state=Base64(redirect|appType)}。
     * 仅用于启动考核、单人/批量评分、考核结果公示；OA 待办请用 {@link #buildOaRedirectUrl(String)}。
     *
     * @param targetUrl 登录成功后打开的 HR 业务页完整 URL（未编码，写入 state）
     */
    public static String buildFeishuMessageUrl(String targetUrl) {
        if (StringUtils.isBlank(targetUrl)) {
            return "";
        }

        try {
            StateValidator stateValidator = SpringContextHolder.getBean(StateValidator.class);
            AppConfigService appConfigService = SpringContextHolder.getBean(AppConfigService.class);
            AppConfig appConfig = appConfigService.getPrimaryApp("feishu");
            if (appConfig == null || StringUtils.isBlank(appConfig.getAppType())) {
                throw new IllegalStateException("oauth-config 未配置 feishu 主应用 appType");
            }
            String state = stateValidator.generate(targetUrl, appConfig.getAppType());
           String url =  UriComponentsBuilder.fromUriString(appConfigService.getShrServerName() + FEISHU_AUTH_PATH)
                    .queryParam("state", state)
                    .build(true)
                    .toUriString();
                    logger.error("integration 单点地址：" +url); 

            return url;
        } catch (Exception e) {
            logger.error("integration 单点地址构建失败，回退 oAToSHR，targetUrl=" + targetUrl, e);
            return buildOaRedirectUrl(targetUrl);
        }
    }

    /**
     * OA 待办跳转地址：{@code BASE_HOST + urlEncode(targetUrl)}（oAToSHR）。
     */
    public static String buildOaRedirectUrl(String targetUrl) {
        if (StringUtils.isBlank(targetUrl)) {
            return "";
        }
        return BASE_HOST + urlEncode(targetUrl);
    }


    private static String resolveHrOrgId(String hrOrgId) {
        if (hrOrgId == null || hrOrgId.trim().isEmpty()) {
            return DEFAULT_HR_ORG_ID;
        }
        return hrOrgId.trim();
    }

}
