package roadmapsync

import "testing"

func readyExpected() Identity {
	return Identity{
		RoadmapMilestonePath: "agent-roadmap/phase/agent-ops-mcp-control-plane/milestones/milestone-work-item-creation-sync.md",
		Provider:             "plane",
		Tenant:               "general",
		Project:              "NOMAD",
		WorkItemID:           "NOMAD-13",
	}
}

func scannedReady() ScannedMilestone {
	return ScannedMilestone{
		Path:     "agent-roadmap/phase/agent-ops-mcp-control-plane/milestones/milestone-work-item-creation-sync.md",
		Identity: readyExpected(),
	}
}

func TestMatchDevelopMilestoneReady(t *testing.T) {
	in := MatchInput{
		Scan: ScanResult{
			Revision: Revision{Branch: "develop", Revision: "abc123"},
			ChangedFiles: []string{
				"services/core/main.go",
				"./agent-roadmap/phase/agent-ops-mcp-control-plane/milestones/milestone-work-item-creation-sync.md",
			},
			ScannedMilestones: []ScannedMilestone{scannedReady()},
		},
		Expected: readyExpected(),
	}
	got := MatchDevelopMilestone(in)
	if !got.Ready {
		t.Fatalf("expected ready, got reason %q", got.Reason)
	}
	if got.Reason != reasonReady {
		t.Errorf("reason = %q", got.Reason)
	}
	if got.Revision.Branch != "develop" {
		t.Errorf("revision branch = %q", got.Revision.Branch)
	}
}

func TestMatchDevelopMilestoneNotReady(t *testing.T) {
	milestoneFile := "agent-roadmap/phase/agent-ops-mcp-control-plane/milestones/milestone-work-item-creation-sync.md"
	cases := map[string]struct {
		in         MatchInput
		wantReason string
	}{
		"slot local path / no develop revision": {
			in: MatchInput{
				// A slot-local scan carries no develop revision.
				Scan:     ScanResult{Revision: Revision{Branch: "develop"}, ChangedFiles: []string{milestoneFile}, ScannedMilestones: []ScannedMilestone{scannedReady()}},
				Expected: readyExpected(),
			},
			wantReason: reasonNoRevision,
		},
		"feature branch": {
			in: MatchInput{
				Scan:     ScanResult{Revision: Revision{Branch: "feature/x", Revision: "abc"}, ChangedFiles: []string{milestoneFile}, ScannedMilestones: []ScannedMilestone{scannedReady()}},
				Expected: readyExpected(),
			},
			wantReason: reasonNotOnDevelop,
		},
		"path matches but no scanned identity": {
			in: MatchInput{
				// Path changed on develop, but no parsed provider identity backs it.
				Scan:     ScanResult{Revision: Revision{Branch: "develop", Revision: "abc"}, ChangedFiles: []string{milestoneFile}},
				Expected: readyExpected(),
			},
			wantReason: reasonNoScannedIdentity,
		},
		"path matches but scanned identity has empty fields": {
			in: MatchInput{
				Scan: ScanResult{
					Revision:          Revision{Branch: "develop", Revision: "abc"},
					ChangedFiles:      []string{milestoneFile},
					ScannedMilestones: []ScannedMilestone{{Path: milestoneFile, Identity: Identity{RoadmapMilestonePath: milestoneFile}}},
				},
				Expected: readyExpected(),
			},
			wantReason: reasonNoScannedIdentity,
		},
		"path matches but scanned work item id differs": {
			in: MatchInput{
				Scan: ScanResult{
					Revision:     Revision{Branch: "develop", Revision: "abc"},
					ChangedFiles: []string{milestoneFile},
					ScannedMilestones: []ScannedMilestone{{
						Path:     milestoneFile,
						Identity: Identity{RoadmapMilestonePath: milestoneFile, Provider: "plane", WorkItemID: "NOMAD-99"},
					}},
				},
				Expected: readyExpected(),
			},
			wantReason: reasonIdentityMismatch,
		},
		"path matches but scanned provider differs": {
			in: MatchInput{
				Scan: ScanResult{
					Revision:     Revision{Branch: "develop", Revision: "abc"},
					ChangedFiles: []string{milestoneFile},
					ScannedMilestones: []ScannedMilestone{{
						Path:     milestoneFile,
						Identity: Identity{RoadmapMilestonePath: milestoneFile, Provider: "jira", WorkItemID: "NOMAD-13"},
					}},
				},
				Expected: readyExpected(),
			},
			wantReason: reasonIdentityMismatch,
		},
		"identity mismatch path": {
			in: MatchInput{
				Scan:     ScanResult{Revision: Revision{Branch: "develop", Revision: "abc"}, ChangedFiles: []string{"agent-roadmap/phase/other/milestones/other.md"}},
				Expected: readyExpected(),
			},
			wantReason: reasonNoMilestoneFile,
		},
		"non-milestone changed file": {
			in: MatchInput{
				Scan:     ScanResult{Revision: Revision{Branch: "develop", Revision: "abc"}, ChangedFiles: []string{"agent-roadmap/phase/p/notes.md"}},
				Expected: readyExpected(),
			},
			wantReason: reasonNoMilestoneFile,
		},
		"invalid expected identity": {
			in: MatchInput{
				Scan:     ScanResult{Revision: Revision{Branch: "develop", Revision: "abc"}, ChangedFiles: []string{milestoneFile}},
				Expected: Identity{Provider: "plane"},
			},
			wantReason: reasonInvalidIdentity,
		},
	}
	for name, tc := range cases {
		t.Run(name, func(t *testing.T) {
			got := MatchDevelopMilestone(tc.in)
			if got.Ready {
				t.Fatalf("expected not ready")
			}
			if got.Reason != tc.wantReason {
				t.Errorf("reason = %q, want %q", got.Reason, tc.wantReason)
			}
		})
	}
}

func TestIsMilestonePath(t *testing.T) {
	if !isMilestonePath("agent-roadmap/phase/p/milestones/m.md") {
		t.Errorf("expected milestone path to match")
	}
	for _, p := range []string{
		"agent-roadmap/phase/p/milestones/m.txt",
		"agent-roadmap/phase/p/notes/m.md",
		"agent-roadmap/milestones/m.md",
		"other/phase/p/milestones/m.md",
	} {
		if isMilestonePath(p) {
			t.Errorf("path %q should not match", p)
		}
	}
}
