package knowledgeqa

import (
	"regexp"
	"strings"
	"testing"

	"github.com/stretchr/testify/require"

	"github.com/tidbcloud/AgentTeam/internal/forwarder"
)

func TestRenderRuntimeAnswerLinksMarkersAcrossClaimsAndDeduplicatesCitations(t *testing.T) {
	sharedCitation := forwarder.KnowledgeQARuntimeCitation{
		KnowledgeBaseID: "kb_1", SourceID: "src_1", RootKind: "primary",
		RepoRole: "primary", Revision: "sha_1", Path: "docs/entry.md",
		LineStart: 3, LineEnd: 8,
	}
	answer, citations, err := renderRuntimeAnswer(
		"kqs_12345678",
		[]forwarder.KnowledgeQARuntimeClaim{
			{
				Text: "入口（[E1]）与详情 [E2]。", EvidenceIDs: []string{"E1", "E2"},
			},
			{
				Text: "第二条结论。", EvidenceIDs: []string{"E3"},
			},
		},
		[]forwarder.KnowledgeQARuntimeEvidence{
			{ID: "E1", Citation: sharedCitation},
			{ID: "E2", Citation: sharedCitation},
			{ID: "E3", Citation: forwarder.KnowledgeQARuntimeCitation{
				KnowledgeBaseID: "kb_1", SourceID: "src_2", RootKind: "insights",
				RepoRole: "insights", Revision: "sha_2", Path: "runbook.md",
				LineStart: 1, LineEnd: 2,
			}},
		},
	)
	require.NoError(t, err)
	require.Len(t, citations, 2)
	require.NotEmpty(t, citations[0].ID)
	require.NotEqual(t, citations[0].ID, citations[1].ID)

	sharedHref := "agentteam-kqa-citation://kqs_12345678/" + citations[0].ID
	require.Contains(t, answer, "入口（[E1]("+sharedHref+")）")
	require.Contains(t, answer, "[E2]("+sharedHref+")")
	require.NotContains(t, answer, "入口（）")
	require.Contains(t, answer, "第二条结论。\n\n[E3](agentteam-kqa-citation://kqs_12345678/"+citations[1].ID+")")
}

func TestRenderRuntimeAnswerLinksSingleVerifiedMarkerOnly(t *testing.T) {
	answer, citations, err := renderRuntimeAnswer(
		"kqs_12345678",
		[]forwarder.KnowledgeQARuntimeClaim{{
			Text: "Verified [E1], unsupported [E9].", EvidenceIDs: []string{"E1", "E9"},
		}},
		[]forwarder.KnowledgeQARuntimeEvidence{{
			ID: "E1", Citation: forwarder.KnowledgeQARuntimeCitation{
				KnowledgeBaseID: "kb_1", SourceID: "src_1", RootKind: "primary",
				RepoRole: "primary", Revision: "sha_1", Path: "README.md",
				LineStart: 1, LineEnd: 1,
			},
		}},
	)
	require.NoError(t, err)
	require.Len(t, citations, 1)
	require.Regexp(t, regexp.MustCompile(`Verified \[E1\]\(agentteam-kqa-citation://kqs_12345678/kqc_[a-z0-9]+\), unsupported \[E9\]\.`), answer)
}

func TestRenderRuntimeAnswerPreservesWebCitationForExistingFootnoteLinks(t *testing.T) {
	answer, citations, err := renderRuntimeAnswer(
		"kqs_12345678",
		[]forwarder.KnowledgeQARuntimeClaim{{
			Text: "The current release is documented online. [E1]", EvidenceIDs: []string{"E1"},
		}},
		[]forwarder.KnowledgeQARuntimeEvidence{{
			ID: "E1", Citation: forwarder.KnowledgeQARuntimeCitation{
				CitationKind: "web", URL: "https://example.com/releases", Title: "Release notes",
				Snippet: "Current release notes", FetchedAt: "2026-08-04T09:00:00Z",
			},
		}},
	)
	require.NoError(t, err)
	require.Len(t, citations, 1)
	require.Equal(t, "web", citations[0].CitationKind)
	require.Equal(t, "https://example.com/releases", citations[0].URL)
	require.Equal(t, "Release notes", citations[0].Title)
	require.NotNil(t, citations[0].FetchedAt)
	require.Contains(t, answer, "[E1](https://example.com/releases)")
	require.NotContains(t, answer, "agentteam-kqa-citation://")
}

func TestRenderRuntimeAnswerResolvesModelAuthoredEvidenceLinks(t *testing.T) {
	answer, citations, err := renderRuntimeAnswer(
		"kqs_12345678",
		[]forwarder.KnowledgeQARuntimeClaim{{
			Text: "Verified [E1](agentteam-kqa-citation://kqs_model/kqc_0123456789abcdef0123456789abcdef), " +
				"external [E2](https://example.com/not-a-citation), unsupported [E9](agentteam-kqa-citation://kqs_model/kqc_deadbeef).\n\n" +
				"Inline code stays `[E1]`.\n\n```text\n[E2]\n```",
			EvidenceIDs: []string{"E1", "E2", "E9"},
		}},
		[]forwarder.KnowledgeQARuntimeEvidence{
			{ID: "E1", Citation: forwarder.KnowledgeQARuntimeCitation{
				KnowledgeBaseID: "kb_1", SourceID: "src_1", RootKind: "primary",
				RepoRole: "primary", Revision: "sha_1", Path: "README.md",
				LineStart: 1, LineEnd: 1,
			}},
			{ID: "E2", Citation: forwarder.KnowledgeQARuntimeCitation{
				KnowledgeBaseID: "kb_1", SourceID: "src_1", RootKind: "primary",
				RepoRole: "primary", Revision: "sha_1", Path: "docs/design.md",
				LineStart: 4, LineEnd: 8,
			}},
		},
	)
	require.NoError(t, err)
	require.Len(t, citations, 2)

	e1Href := "agentteam-kqa-citation://kqs_12345678/" + citations[0].ID
	e2Href := "agentteam-kqa-citation://kqs_12345678/" + citations[1].ID
	require.Contains(t, answer, "Verified [E1]("+e1Href+"), external [E2]("+e2Href+"), unsupported [E9].")
	require.NotContains(t, answer, "kqs_model")
	require.NotContains(t, answer, "https://example.com/not-a-citation")
	require.Equal(t, 2, strings.Count(answer, "agentteam-kqa-citation://"))
	require.Contains(t, answer, "Inline code stays `[E1]`.")
	require.Contains(t, answer, "```text\n[E2]\n```")
}

func TestRenderRuntimeAnswerDoesNotCreateNestedMarkdownLinks(t *testing.T) {
	answer, citations, err := renderRuntimeAnswer(
		"kqs_12345678",
		[]forwarder.KnowledgeQARuntimeClaim{{
			Text:        "Nested [source [E1]](https://example.com), image ![E1](diagram.png).\n\n[E1]: https://example.com/reference",
			EvidenceIDs: []string{"E1"},
		}},
		[]forwarder.KnowledgeQARuntimeEvidence{{
			ID: "E1", Citation: forwarder.KnowledgeQARuntimeCitation{
				KnowledgeBaseID: "kb_1", SourceID: "src_1", RootKind: "primary",
				RepoRole: "primary", Revision: "sha_1", Path: "README.md",
				LineStart: 1, LineEnd: 1,
			},
		}},
	)
	require.NoError(t, err)
	require.Len(t, citations, 1)
	require.Contains(t, answer, "Nested [source [E1]](https://example.com), image ![E1](diagram.png).")
	require.Contains(t, answer, "[E1]: https://example.com/reference")
	require.Contains(t, answer, "\n\n[E1](agentteam-kqa-citation://kqs_12345678/"+citations[0].ID+")")
}

func TestRenderRuntimeAnswerMergesCitationOnlyClaimAndCollapsesAdjacentDuplicate(t *testing.T) {
	answer, citations, err := renderRuntimeAnswer(
		"kqs_12345678",
		[]forwarder.KnowledgeQARuntimeClaim{
			{Text: "The scheduler waits for capacity. [E1]", EvidenceIDs: []string{"E1"}},
			{Text: "[E1] [E2] [E3]", EvidenceIDs: []string{"E1", "E2", "E3"}},
		},
		[]forwarder.KnowledgeQARuntimeEvidence{
			{ID: "E1", Citation: forwarder.KnowledgeQARuntimeCitation{
				KnowledgeBaseID: "kb_1", SourceID: "src_1", RootKind: "primary",
				RepoRole: "primary", Revision: "sha_1", Path: "scheduler.go",
				LineStart: 10, LineEnd: 20,
			}},
			{ID: "E2", Citation: forwarder.KnowledgeQARuntimeCitation{
				KnowledgeBaseID: "kb_1", SourceID: "src_1", RootKind: "primary",
				RepoRole: "primary", Revision: "sha_1", Path: "scheduler.go",
				LineStart: 10, LineEnd: 20,
			}},
			{ID: "E3", Citation: forwarder.KnowledgeQARuntimeCitation{
				KnowledgeBaseID: "kb_1", SourceID: "src_1", RootKind: "primary",
				RepoRole: "primary", Revision: "sha_1", Path: "quota.go",
				LineStart: 30, LineEnd: 40,
			}},
		},
	)

	require.NoError(t, err)
	require.Len(t, citations, 2)
	require.Equal(t, 1, strings.Count(answer, "[E1]("))
	require.NotContains(t, answer, "[E2](")
	require.Equal(t, 1, strings.Count(answer, "[E3]("))
	require.NotContains(t, answer, "\n\n[E1]")
	require.Regexp(t, regexp.MustCompile(`capacity\. \[E1\]\([^\n]+\) \[E3\]\([^\n]+\)$`), answer)
}

func TestRenderRuntimeAnswerGoldenMarkdownStructuresStayIntact(t *testing.T) {
	cases := []struct {
		name     string
		markdown string
		want     string
	}{
		{name: "list", markdown: "- First item\n- Second item", want: "- First item\n- Second item\n\n[E1]("},
		{name: "table", markdown: "| Key | Value |\n| --- | --- |\n| limit | 10 |", want: "| Key | Value |\n| --- | --- |\n| limit | 10 |\n\n[E1]("},
		{name: "fenced code", markdown: "```go\nfmt.Println(\"[E1]\")\n```", want: "```go\nfmt.Println(\"[E1]\")\n```\n\n[E1]("},
		{name: "mermaid", markdown: "```mermaid\ngraph TD\nA-->B\n```", want: "```mermaid\ngraph TD\nA-->B\n```\n\n[E1]("},
		{name: "inline code", markdown: "`[E1]` stays literal.", want: "`[E1]` stays literal. [E1]("},
	}
	for _, test := range cases {
		t.Run(test.name, func(t *testing.T) {
			answer, citations, err := renderRuntimeAnswer(
				"kqs_12345678",
				[]forwarder.KnowledgeQARuntimeClaim{
					{Text: test.markdown},
					{Text: "[E1]", EvidenceIDs: []string{"E1"}},
				},
				[]forwarder.KnowledgeQARuntimeEvidence{{
					ID: "E1", Citation: forwarder.KnowledgeQARuntimeCitation{
						KnowledgeBaseID: "kb_1", SourceID: "src_1", RootKind: "primary",
						RepoRole: "primary", Revision: "sha_1", Path: "answer.md",
						LineStart: 1, LineEnd: 4,
					},
				}},
			)

			require.NoError(t, err)
			require.Len(t, citations, 1)
			require.Contains(t, answer, test.want)
			require.Equal(t, 1, strings.Count(answer, "agentteam-kqa-citation://"))
		})
	}
}
