package tech.easyflow.admin.controller.ai;

import cn.dev33.satoken.annotation.SaCheckPermission;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import tech.easyflow.ai.entity.Workflow;
import tech.easyflow.ai.entity.WorkflowShare;
import tech.easyflow.ai.service.KnowledgeShareAuditService;
import tech.easyflow.ai.service.WorkflowService;
import tech.easyflow.ai.service.WorkflowShareService;
import tech.easyflow.ai.share.WorkflowSharePolicy;
import tech.easyflow.ai.vo.WorkflowShareCreateResult;
import tech.easyflow.common.domain.Result;
import tech.easyflow.common.entity.LoginAccount;
import tech.easyflow.common.satoken.util.SaTokenUtil;
import tech.easyflow.common.util.RequestUtil;
import tech.easyflow.common.web.exceptions.BusinessException;
import tech.easyflow.common.web.jsonbody.JsonBody;
import tech.easyflow.system.enums.CategoryResourceType;
import tech.easyflow.system.enums.ResourceAction;
import tech.easyflow.system.service.ResourceAccessService;

import javax.annotation.Resource;
import java.math.BigInteger;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Map;

/**
 * 工作流分享管理接口。
 */
@RestController
@RequestMapping("/api/v1/workflowShare")
public class WorkflowShareController {

    @Resource
    private WorkflowShareService workflowShareService;

    @Resource
    private WorkflowService workflowService;

    @Resource
    private ResourceAccessService resourceAccessService;

    @Resource
    private KnowledgeShareAuditService knowledgeShareAuditService;

    /**
     * 创建或刷新已发布工作流的对话分享链接。
     *
     * @param request HTTP 请求
     * @param workflowId 工作流 ID
     * @return 分享创建结果
     */
    @PostMapping("/url/create")
    @SaCheckPermission("/api/v1/workflow/save")
    public Result<WorkflowShareCreateResult> createUrlShare(
            HttpServletRequest request,
            @JsonBody("workflowId") BigInteger workflowId
    ) {
        Workflow workflow = workflowService.getById(workflowId);
        if (workflow == null) {
            throw new BusinessException("工作流不存在");
        }
        resourceAccessService.assertAccess(
                CategoryResourceType.WORKFLOW,
                workflow,
                ResourceAction.MANAGE,
                "无权限分享工作流"
        );
        LoginAccount loginAccount = SaTokenUtil.getLoginAccount();
        WorkflowShareCreateResult result = workflowShareService.createChatShare(
                workflowId,
                loginAccount.getTenantId(),
                loginAccount.getDeptId(),
                loginAccount.getId(),
                buildShareBaseUrl(request)
        );
        knowledgeShareAuditService.log(
                loginAccount.getId(),
                "创建工作流对话分享",
                "WORKFLOW_CHAT_SHARE_CREATE",
                request.getRequestURI(),
                Map.of("workflowId", workflowId, "shareId", result.getId())
        );
        return Result.ok(result);
    }

    /**
     * 解析当前对话分享指向的工作流。
     *
     * @param request HTTP 请求
     * @return 工作流标识
     */
    @GetMapping("/resolve")
    public Result<Map<String, BigInteger>> resolveUrlShare(HttpServletRequest request) {
        LoginAccount loginAccount = SaTokenUtil.getLoginAccount();
        WorkflowShare share = workflowShareService.resolveChatShare(
                request.getHeader(WorkflowSharePolicy.CHAT_SHARE_KEY_HEADER),
                loginAccount.getTenantId()
        );
        return Result.ok(Map.of("workflowId", share.getWorkflowId()));
    }

    /**
     * 根据管理端来源构建工作流分享基础 URL。
     *
     * @param request HTTP 请求
     * @return 工作流独立分享页 URL
     */
    private String buildShareBaseUrl(HttpServletRequest request) {
        String refererBaseUrl = extractFrontendBaseUrl(RequestUtil.getReferer(request));
        if (refererBaseUrl != null) {
            return refererBaseUrl + "/share/workflow";
        }

        String forwardedOrigin = buildForwardedOrigin(request);
        if (forwardedOrigin != null) {
            return forwardedOrigin
                    + normalizeBasePath(firstHeaderValue(request.getHeader("X-Forwarded-Prefix")))
                    + "/share/workflow";
        }

        String origin = normalizeOrigin(request.getHeader("Origin"));
        if (origin != null) {
            return origin + normalizeBasePath(request.getContextPath()) + "/share/workflow";
        }
        StringBuilder builder = new StringBuilder();
        builder.append(request.getScheme()).append("://").append(request.getServerName());
        if (request.getServerPort() != 80 && request.getServerPort() != 443) {
            builder.append(':').append(request.getServerPort());
        }
        return builder.append(normalizeBasePath(request.getContextPath()))
                .append("/share/workflow")
                .toString();
    }

    /**
     * 从来源地址提取前端 origin 与部署基路径。
     *
     * @param sourceUrl 来源地址
     * @return origin 与部署基路径，无法解析时返回 {@code null}
     */
    private String extractFrontendBaseUrl(String sourceUrl) {
        if (sourceUrl == null || sourceUrl.isBlank()) {
            return null;
        }
        try {
            URI uri = new URI(sourceUrl.trim());
            if (uri.getScheme() == null || uri.getHost() == null) {
                return null;
            }
            String origin = extractOrigin(sourceUrl);
            return origin == null ? null : origin + inferFrontendBasePath(uri.getPath());
        } catch (URISyntaxException e) {
            return null;
        }
    }

    /**
     * 从前端页面路径推断部署基路径。
     *
     * @param path 页面路径
     * @return 规范化后的部署基路径
     */
    private String inferFrontendBasePath(String path) {
        if (path == null || path.isBlank() || "/".equals(path)) {
            return "";
        }
        for (String marker : new String[]{"/ai/", "/auth/", "/share/"}) {
            int markerIndex = path.indexOf(marker);
            if (markerIndex > 0) {
                return normalizeBasePath(path.substring(0, markerIndex));
            }
            if (markerIndex == 0) {
                return "";
            }
        }
        return "";
    }

    /**
     * 规范化部署基路径。
     *
     * @param basePath 原始基路径
     * @return 无尾斜杠的基路径
     */
    private String normalizeBasePath(String basePath) {
        if (basePath == null || basePath.isBlank() || "/".equals(basePath.trim())) {
            return "";
        }
        String normalized = basePath.trim();
        if (!normalized.startsWith("/")) {
            normalized = "/" + normalized;
        }
        while (normalized.endsWith("/") && normalized.length() > 1) {
            normalized = normalized.substring(0, normalized.length() - 1);
        }
        return normalized;
    }

    /**
     * 按反向代理头构建外部访问 origin。
     *
     * @param request HTTP 请求
     * @return 外部 origin，缺少代理头时返回 {@code null}
     */
    private String buildForwardedOrigin(HttpServletRequest request) {
        String proto = firstHeaderValue(request.getHeader("X-Forwarded-Proto"));
        String host = firstHeaderValue(request.getHeader("X-Forwarded-Host"));
        if (proto == null || host == null) {
            return null;
        }
        return normalizeOrigin(proto + "://" + host);
    }

    /**
     * 从 URL 提取 origin。
     *
     * @param url 完整 URL
     * @return origin，无法解析时返回 {@code null}
     */
    private String extractOrigin(String url) {
        if (url == null || url.isBlank()) {
            return null;
        }
        try {
            URI uri = new URI(url.trim());
            if (uri.getScheme() == null || uri.getHost() == null) {
                return null;
            }
            StringBuilder builder = new StringBuilder();
            builder.append(uri.getScheme()).append("://").append(uri.getHost());
            if (uri.getPort() != -1 && uri.getPort() != 80 && uri.getPort() != 443) {
                builder.append(':').append(uri.getPort());
            }
            return builder.toString();
        } catch (URISyntaxException e) {
            return null;
        }
    }

    /**
     * 规范化 origin。
     *
     * @param origin 原始 origin
     * @return 规范化结果
     */
    private String normalizeOrigin(String origin) {
        return extractOrigin(origin);
    }

    /**
     * 读取代理头的首个有效值。
     *
     * @param value 原始请求头
     * @return 首个有效值
     */
    private String firstHeaderValue(String value) {
        if (value == null || value.isBlank()) {
            return null;
        }
        int commaIndex = value.indexOf(',');
        String normalized = commaIndex >= 0 ? value.substring(0, commaIndex) : value;
        normalized = normalized.trim();
        return normalized.isEmpty() ? null : normalized;
    }
}
