package knowledgeqa

import (
	"fmt"
	"net/url"
	pathpkg "path"
	"strings"
)

func knowledgeQACitationTarget(citation Citation) (string, bool) {
	knowledgeBaseID := strings.TrimSpace(citation.KnowledgeBaseID)
	if knowledgeBaseID == "" {
		return "", false
	}
	knowledgeBaseRoute := "/kb/" + url.PathEscape(knowledgeBaseID)
	switch strings.TrimSpace(citation.RootKind) {
	case "lexicon":
		if strings.TrimSpace(citation.RepoRole) != "wiki" || strings.TrimSpace(citation.SourceID) != "" {
			return "", false
		}
		return knowledgeBaseRoute, true
	case "insights":
		if strings.TrimSpace(citation.RepoRole) != "insights" {
			return "", false
		}
		sourceRoute, ok := knowledgeQASourceRoute(knowledgeBaseRoute, citation.SourceID)
		if !ok {
			return "", false
		}
		slug, ok := knowledgeQAWikiSlug(citation.Path)
		if !ok {
			return "", false
		}
		return sourceRoute + "/wiki/" + url.PathEscape(slug), true
	case "primary":
		role := strings.TrimSpace(citation.RepoRole)
		// Legacy citations persisted repo_role "canonical" before the primary
		// rename; both spellings resolve identically.
		if role != "primary" && role != "canonical" && role != "mirror" {
			return "", false
		}
		sourceRoute, ok := knowledgeQASourceRoute(knowledgeBaseRoute, citation.SourceID)
		if !ok {
			return "", false
		}
		filePath, ok := knowledgeQARelativePath(citation.Path)
		revision := strings.TrimSpace(citation.Revision)
		if !ok || revision == "" {
			return "", false
		}
		target := sourceRoute + "/blob/" + url.PathEscape(revision) + "/" + escapePathSegments(filePath)
		resolvedRef := strings.TrimSpace(citation.ResolvedRef)
		resolvedRefKind := strings.TrimSpace(citation.ResolvedRefKind)
		if resolvedRef != "" && len(resolvedRef) <= 255 &&
			(resolvedRefKind == "branch" || resolvedRefKind == "tag") {
			query := url.Values{}
			query.Set("sourceRef", resolvedRef)
			query.Set("sourceRefKind", resolvedRefKind)
			target += "?" + query.Encode()
		}
		if citation.LineStart > 0 {
			target += fmt.Sprintf("#L%d", citation.LineStart)
		}
		return target, true
	default:
		return "", false
	}
}

func knowledgeQASourceRoute(knowledgeBaseRoute, sourceID string) (string, bool) {
	sourceID = strings.TrimSpace(sourceID)
	if sourceID == "" {
		return "", false
	}
	return knowledgeBaseRoute + "/sources/" + url.PathEscape(sourceID), true
}

func knowledgeQAWikiSlug(rawPath string) (string, bool) {
	filePath, ok := knowledgeQARelativePath(rawPath)
	if !ok {
		return "", false
	}
	slug := strings.TrimSuffix(filePath, ".md")
	slug = strings.TrimSuffix(slug, ".markdown")
	slug = strings.Trim(slug, "/")
	return slug, slug != ""
}

func knowledgeQARelativePath(rawPath string) (string, bool) {
	rawPath = strings.TrimSpace(rawPath)
	if rawPath == "" || strings.ContainsRune(rawPath, '\x00') ||
		strings.Contains(rawPath, "\\") || pathpkg.IsAbs(rawPath) {
		return "", false
	}
	for _, segment := range strings.Split(rawPath, "/") {
		if segment == ".." {
			return "", false
		}
	}
	cleaned := pathpkg.Clean(rawPath)
	if cleaned == "." || cleaned == ".." || strings.HasPrefix(cleaned, "../") {
		return "", false
	}
	return cleaned, true
}

func escapePathSegments(value string) string {
	parts := strings.Split(value, "/")
	for index, part := range parts {
		parts[index] = url.PathEscape(part)
	}
	return strings.Join(parts, "/")
}
