package com.kingdee.eas.custom.weaverTodo.config;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.Properties;

/**
 * 从 EAS_HOME/server/properties/baoye/weaverTodoConfig.properties 加载。
 * 待办走 receiveRequestInfo；通知走消息中心 sendMsg。二者共用 OpenAPI host/token。
 * getInstance 按文件 lastModified 热加载。
 */
public class WeaverTodoConfig {
    private static final Logger logger = Logger.getLogger(WeaverTodoConfig.class);

    private static final String DEFAULT_PATH =
            System.getProperty("EAS_HOME") + "/server/properties/baoye/weaverTodoConfig.properties";

    private static final Object LOCK = new Object();
    private static volatile WeaverTodoConfig instance;
    private static volatile long loadedMtime = Long.MIN_VALUE;
    private static volatile String loadedPath;

    /**
     * 按配置文件路径与修改时间取实例；有变更则重新加载。
     */
    public static WeaverTodoConfig getInstance() {
        String path = System.getProperty("WEAVER_TODO_CONFIG_PATH", DEFAULT_PATH);
        File file = new File(path);
        long mtime = file.exists() ? file.lastModified() : 0L;
        WeaverTodoConfig cur = instance;
        if (cur != null && mtime == loadedMtime && path.equals(loadedPath)) {
            return cur;
        }
        synchronized (LOCK) {
            if (instance != null && mtime == loadedMtime && path.equals(loadedPath)) {
                return instance;
            }
            WeaverTodoConfig next = new WeaverTodoConfig(path, mtime);
            instance = next;
            loadedMtime = mtime;
            loadedPath = path;
            return next;
        }
    }

    private final String openapiHost;
    private final String authorizePath;
    private final String accessTokenPath;
    private final String receivePath;
    private final String sendMsgPath;
    private final String corpid;
    private final String appKey;
    private final String appSecret;
    private final String syscode;
    private final String shrServerName;
    private final String ssoAppId;
    /** 待办 pcurl 的 SSO 入口，默认 /qy/auth/weaver/app.do */
    private final String ssoEntryPath;
    private final String approvePcPath;
    private final boolean enabled;
    private final int wfDelayMs;
    private final String notifyTenantKey;
    private final int notifyModuleId;
    private final int notifyEventId;
    private final String notifySenderName;
    private final String notifySenderWorkCode;
    private final int[] notifyChannels;

    private WeaverTodoConfig(String path, long mtime) {
        Properties p = new Properties();
        boolean loaded = false;
        try {
            InputStreamReader reader = new InputStreamReader(new FileInputStream(path), StandardCharsets.UTF_8);
            try {
                p.load(reader);
                loaded = true;
                logger.info("已加载 weaverTodoConfig: " + path + ", mtime=" + mtime);
            } finally {
                reader.close();
            }
        } catch (Exception e) {
            logger.error("加载 weaverTodoConfig 失败: " + path + "，推送将关闭", e);
        }
        boolean wantEnable = loaded && !"false".equalsIgnoreCase(p.getProperty("weaver.todo.enabled", "true"));
        this.openapiHost = trimSlash(p.getProperty("weaver.openapi.host", ""));
        this.authorizePath = normalizePath(p.getProperty("weaver.openapi.authorizePath",
                "/papi/openapi/oauth2/authorize"));
        this.accessTokenPath = normalizePath(p.getProperty("weaver.openapi.accessTokenPath",
                "/papi/openapi/oauth2/access_token"));
        this.receivePath = normalizePath(p.getProperty("weaver.openapi.receivePath",
                "/papi/openapi/api/open_intunifytodo/server_engine/receiveRequestInfo"));
        this.sendMsgPath = normalizePath(p.getProperty("weaver.openapi.sendMsgPath",
                "/papi/openapi/api/mc/msg/sendMsg"));
        this.corpid = p.getProperty("weaver.corpid", "").trim();
        this.appKey = p.getProperty("weaver.app_key", "").trim();
        this.appSecret = p.getProperty("weaver.app_secret", "").trim();
        this.syscode = p.getProperty("weaver.syscode", "s-HRCloud").trim();
        this.shrServerName = trimSlash(p.getProperty("weaver.shrServerName", ""));
        this.ssoAppId = p.getProperty("weaver.sso.appId", "").trim();
        this.ssoEntryPath = normalizePath(p.getProperty("weaver.sso.entryPath",
                "/qy/auth/weaver/app.do"));
        this.approvePcPath = p.getProperty("weaver.path.pc.approve",
                "/easweb/webviews/workflow/transferApprove.jsp").trim();
        this.wfDelayMs = parseInt(p.getProperty("weaver.wf.delayMs", "3000"), 3000);
        // 通知固定参数以 properties 为准；缺省按生产。测试请配 moduleId=139141 eventId=287602
        this.notifyTenantKey = p.getProperty("weaver.notify.tenantKey", "t6srq5l4vh").trim();
        this.notifyModuleId = parseInt(p.getProperty("weaver.notify.moduleId", "100011"), 100011);
        this.notifyEventId = parseInt(p.getProperty("weaver.notify.eventId", "241221"), 241221);
        this.notifySenderName = p.getProperty("weaver.notify.senderName", "SHR").trim();
        this.notifySenderWorkCode = p.getProperty("weaver.notify.senderWorkCode", "").trim();
        this.notifyChannels = parseChannels(p.getProperty("weaver.notify.channels", "1"));
        logger.info("OpenAPI paths host=" + openapiHost
                + " authorize=" + authorizePath
                + " token=" + accessTokenPath
                + " receive=" + receivePath
                + " sendMsg=" + sendMsgPath
                + " syscode=" + syscode
                + " notifyTenant=" + notifyTenantKey
                + " moduleId=" + notifyModuleId
                + " eventId=" + notifyEventId);
        if (wantEnable && StringUtils.isAnyBlank(openapiHost, corpid, appKey, appSecret, syscode, shrServerName, ssoAppId)) {
            logger.error("weaverTodoConfig 必填项缺失，推送已关闭");
            this.enabled = false;
        } else {
            this.enabled = wantEnable;
        }
    }

    private static int[] parseChannels(String s) {
        if (s == null || s.trim().isEmpty()) {
            return new int[]{1};
        }
        String[] parts = s.split(",");
        int[] arr = new int[parts.length];
        int n = 0;
        for (int i = 0; i < parts.length; i++) {
            try {
                arr[n++] = Integer.parseInt(parts[i].trim());
            } catch (Exception ignored) {
            }
        }
        if (n == 0) {
            return new int[]{1};
        }
        if (n == arr.length) {
            return arr;
        }
        int[] out = new int[n];
        System.arraycopy(arr, 0, out, 0, n);
        return out;
    }

    private static String trimSlash(String s) {
        if (s == null) {
            return "";
        }
        s = s.trim();
        while (s.endsWith("/")) {
            s = s.substring(0, s.length() - 1);
        }
        return s;
    }

    private static String normalizePath(String s) {
        if (s == null || s.trim().isEmpty()) {
            return "";
        }
        s = s.trim();
        if (!s.startsWith("/")) {
            s = "/" + s;
        }
        while (s.endsWith("/") && s.length() > 1) {
            s = s.substring(0, s.length() - 1);
        }
        return s;
    }

    private static int parseInt(String s, int def) {
        try {
            return Integer.parseInt(s.trim());
        } catch (Exception e) {
            return def;
        }
    }

    public boolean isEnabled() {
        return enabled;
    }

    public String getOpenapiHost() {
        return openapiHost;
    }

    public String getAuthorizePath() {
        return authorizePath;
    }

    public String getAccessTokenPath() {
        return accessTokenPath;
    }

    public String getReceivePath() {
        return receivePath;
    }

    public String getSendMsgPath() {
        return sendMsgPath;
    }

    public String getCorpid() {
        return corpid;
    }

    public String getAppKey() {
        return appKey;
    }

    public String getAppSecret() {
        return appSecret;
    }

    public String getSyscode() {
        return syscode;
    }

    public String getShrServerName() {
        return shrServerName;
    }

    public String getSsoAppId() {
        return ssoAppId;
    }

    public String getSsoEntryPath() {
        return ssoEntryPath;
    }

    public String getApprovePcPath() {
        return approvePcPath;
    }

    public int getWfDelayMs() {
        return wfDelayMs;
    }

    public String getNotifyTenantKey() {
        return notifyTenantKey;
    }

    public int getNotifyModuleId() {
        return notifyModuleId;
    }

    public int getNotifyEventId() {
        return notifyEventId;
    }

    public String getNotifySenderName() {
        return notifySenderName;
    }

    public String getNotifySenderWorkCode() {
        return notifySenderWorkCode;
    }

    public int[] getNotifyChannels() {
        return notifyChannels == null ? new int[]{1} : notifyChannels.clone();
    }
}
