package tech.easyflow.admin.controller.ai;

import cn.dev33.satoken.annotation.SaCheckPermission;
import jakarta.servlet.http.HttpServletRequest;
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.dto.KnowledgeShareApiGrantRequest;
import tech.easyflow.ai.entity.DocumentCollection;
import tech.easyflow.ai.enums.KnowledgeShareActionScope;
import tech.easyflow.ai.service.DocumentCollectionService;
import tech.easyflow.ai.service.KnowledgeShareAuditService;
import tech.easyflow.ai.service.KnowledgeSharePermissionService;
import tech.easyflow.ai.service.KnowledgeShareService;
import tech.easyflow.ai.vo.KnowledgeShareUrlCreateResult;
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/knowledgeShare")
public class KnowledgeShareController {

    @Resource
    private KnowledgeShareService knowledgeShareService;
    @Resource
    private KnowledgeSharePermissionService knowledgeSharePermissionService;
    @Resource
    private KnowledgeShareAuditService knowledgeShareAuditService;
    @Resource
    private ResourceAccessService resourceAccessService;
    @Resource
    private DocumentCollectionService documentCollectionService;

    /**
     * 创建 URL 分享。
     *
     * @param request HTTP 请求
     * @param knowledgeId 知识库 ID
     * @return 创建结果
     */
    @PostMapping("/url/create")
    @SaCheckPermission("/api/v1/documentCollection/save")
    public Result<KnowledgeShareUrlCreateResult> createUrlShare(HttpServletRequest request, @JsonBody("knowledgeId") BigInteger knowledgeId) {
        assertManagePermission(knowledgeId);
        LoginAccount loginAccount = SaTokenUtil.getLoginAccount();
        KnowledgeShareUrlCreateResult result = knowledgeShareService.createUrlShare(
            knowledgeId,
            loginAccount.getTenantId(),
            loginAccount.getDeptId(),
            loginAccount.getId(),
            buildShareBaseUrl(request),
            KnowledgeShareActionScope.defaultUrlScopes()
        );
        knowledgeShareAuditService.log(
            loginAccount.getId(),
            "创建知识库 URL 分享",
            "KNOWLEDGE_SHARE_CREATE",
            request.getRequestURI(),
            Map.of("knowledgeId", knowledgeId, "shareId", result.getId())
        );
        return Result.ok(result);
    }

    /**
     * 为系统访问令牌配置知识库 API 分享授权。
     *
     * @param request 授权请求
     * @return 结果
     */
    @PostMapping("/api/grant")
    @SaCheckPermission("/api/v1/documentCollection/save")
    public Result<Void> grantApiShare(@JsonBody KnowledgeShareApiGrantRequest request) {
        assertManagePermission(request.getKnowledgeId());
        knowledgeSharePermissionService.grantApiShare(
            request.getApiKeyId(),
            request.getKnowledgeId(),
            request.getActionScopes()
        );
        LoginAccount loginAccount = SaTokenUtil.getLoginAccount();
        knowledgeShareAuditService.log(
            loginAccount.getId(),
            "配置知识库 API 分享授权",
            "KNOWLEDGE_API_SHARE_GRANT",
            "/api/v1/knowledgeShare/api/grant",
            Map.of(
                "knowledgeId", request.getKnowledgeId(),
                "apiKeyId", request.getApiKeyId(),
                "actionScopes", request.getActionScopes()
            )
        );
        return Result.ok();
    }

    private void assertManagePermission(BigInteger knowledgeId) {
        DocumentCollection knowledge = documentCollectionService.getById(knowledgeId);
        if (knowledge == null) {
            throw new BusinessException("知识库不存在");
        }
        resourceAccessService.assertAccess(
            CategoryResourceType.KNOWLEDGE,
            knowledge,
            ResourceAction.MANAGE,
            "无权限管理知识库"
        );
    }

    private String buildShareBaseUrl(HttpServletRequest request) {
        String referer = RequestUtil.getReferer(request);
        String refererBaseUrl = extractFrontendBaseUrl(referer);
        if (refererBaseUrl != null) {
            return refererBaseUrl + "/share/knowledge";
        }

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

        String origin = normalizeOrigin(request.getHeader("Origin"));
        if (origin != null) {
            return origin + normalizeBasePath(request.getContextPath()) + "/share/knowledge";
        }

        StringBuilder builder = new StringBuilder();
        builder.append(request.getScheme()).append("://").append(request.getServerName());
        if (request.getServerPort() != 80 && request.getServerPort() != 443) {
            builder.append(':').append(request.getServerPort());
        }
        builder.append(normalizeBasePath(request.getContextPath())).append("/share/knowledge");
        return builder.toString();
    }

    private String extractFrontendBaseUrl(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;
            }
            String origin = extractOrigin(url);
            if (origin == null) {
                return null;
            }
            return origin + inferFrontendBasePath(uri.getPath());
        } catch (URISyntaxException e) {
            return null;
        }
    }

    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 "";
    }

    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;
    }

    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);
    }

    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;
        }
    }

    private String normalizeOrigin(String origin) {
        return extractOrigin(origin);
    }

    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;
    }
}
