package tech.easyflow.ai.share;

import tech.easyflow.system.enums.ResourceAction;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.time.Duration;
import java.util.Date;
import java.util.HexFormat;
import java.util.Set;

/**
 * 工作流协作分享的密钥、时效与接口授权策略。
 */
public final class WorkflowSharePolicy {

    /**
     * 工作流协作分享请求头。
     */
    public static final String SHARE_KEY_HEADER = "X-Workflow-Share-Key";

    /**
     * 工作流对话分享请求头。
     */
    public static final String CHAT_SHARE_KEY_HEADER = "X-Workflow-Chat-Share-Key";

    private static final Duration DEFAULT_EXPIRE_DURATION = Duration.ofMinutes(30);
    private static final Duration DEFAULT_CHAT_EXPIRE_DURATION = Duration.ofDays(7);
    private static final Set<String> ALLOWED_REQUESTS = Set.of(
            permissionKey("GET", "/api/v1/workflow/detail", ResourceAction.READ),
            permissionKey("GET", "/api/v1/workflow/getRunningParameters", ResourceAction.READ),
            permissionKey("GET", "/api/v1/workflow/designer/options", ResourceAction.READ),
            permissionKey("GET", "/api/v1/workflow/designer/plugins", ResourceAction.READ),
            permissionKey("GET", "/api/v1/workflow/designer/pluginTinyFlow", ResourceAction.READ),
            permissionKey("GET", "/api/v1/workflow/designer/childWorkflow", ResourceAction.READ),
            permissionKey("GET", "/api/v1/workflow/designer/dataSources", ResourceAction.READ),
            permissionKey("GET", "/api/v1/workflow/designer/catalogs", ResourceAction.READ),
            permissionKey("GET", "/api/v1/workflow/designer/managedTables", ResourceAction.READ),
            permissionKey("GET", "/api/v1/workflow/designer/schema", ResourceAction.READ),
            permissionKey("POST", "/api/v1/workflow/update", ResourceAction.MANAGE),
            permissionKey("POST", "/api/v1/workflow/check", ResourceAction.MANAGE),
            permissionKey("POST", "/api/v1/workflow/singleRun", ResourceAction.USE),
            permissionKey("POST", "/api/v1/workflow/runAsync", ResourceAction.USE),
            permissionKey("POST", "/api/v1/workflow/getChainStatus", ResourceAction.USE),
            permissionKey("POST", "/api/v1/workflow/resume", ResourceAction.USE),
            permissionKey("GET", "/api/v1/workflow/publishApprovalRequirement", ResourceAction.MANAGE),
            permissionKey("POST", "/api/v1/workflow/submitPublishApproval", ResourceAction.MANAGE)
    );

    private WorkflowSharePolicy() {
    }

    /**
     * 计算分享密钥的 SHA-256 摘要。
     *
     * @param shareKey 原始分享密钥
     * @return 十六进制摘要
     */
    public static String hashShareKey(String shareKey) {
        try {
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            byte[] value = digest.digest(shareKey.getBytes(StandardCharsets.UTF_8));
            return HexFormat.of().formatHex(value);
        } catch (NoSuchAlgorithmException e) {
            throw new IllegalStateException("SHA-256 unavailable", e);
        }
    }

    /**
     * 计算默认过期时间。
     *
     * @param createdAt 创建时间
     * @return 创建后 30 分钟的时间
     */
    public static Date defaultExpiresAt(Date createdAt) {
        if (createdAt == null) {
            throw new IllegalArgumentException("创建时间不能为空");
        }
        return new Date(createdAt.getTime() + DEFAULT_EXPIRE_DURATION.toMillis());
    }

    /**
     * 计算对话分享默认过期时间。
     *
     * @param createdAt 创建时间
     * @return 创建后 7 天的时间
     */
    public static Date defaultChatExpiresAt(Date createdAt) {
        if (createdAt == null) {
            throw new IllegalArgumentException("创建时间不能为空");
        }
        return new Date(createdAt.getTime() + DEFAULT_CHAT_EXPIRE_DURATION.toMillis());
    }

    /**
     * 判断 HTTP 请求是否位于工作流协作授权白名单。
     *
     * @param method HTTP 方法
     * @param requestUri 请求路径
     * @param action 资源动作
     * @return 位于白名单时返回 {@code true}
     */
    public static boolean isAllowedRequest(String method, String requestUri, ResourceAction action) {
        if (method == null || requestUri == null || action == null) {
            return false;
        }
        String methodPrefix = method.trim().toUpperCase() + ":";
        String actionSuffix = ":" + action.name();
        for (String allowedRequest : ALLOWED_REQUESTS) {
            if (allowedRequest.startsWith(methodPrefix)
                    && allowedRequest.endsWith(actionSuffix)
                    && requestUri.endsWith(requestUriSuffix(allowedRequest))
            ) {
                return true;
            }
        }
        return false;
    }

    /**
     * 生成请求授权键。
     *
     * @param method HTTP 方法
     * @param path 请求路径
     * @param action 资源动作
     * @return 授权键
     */
    private static String permissionKey(String method, String path, ResourceAction action) {
        return method + ":" + path + ":" + action.name();
    }

    /**
     * 从授权键中读取请求路径。
     *
     * @param permissionKey 授权键
     * @return 请求路径
     */
    private static String requestUriSuffix(String permissionKey) {
        int firstSeparator = permissionKey.indexOf(':');
        int lastSeparator = permissionKey.lastIndexOf(':');
        return permissionKey.substring(firstSeparator + 1, lastSeparator);
    }
}
