package main

import (
	"os"
	"path/filepath"
	"strings"
	"testing"
)

func TestPathMentionedRequiresBoundary(t *testing.T) {
	t.Parallel()

	cell := "GET/POST/PATCH/DELETE /services/data/v63.0/analytics/reports/{reportId} and GET /services/data/v63.0/analytics/reports/{reportId}/describe"
	if pathMentioned(cell, "/services/data/v63.0/analytics/reports") {
		t.Fatalf("base collection path should not match longer detail paths")
	}
	if !pathMentioned(cell, "/services/data/v63.0/analytics/reports/{reportId}") {
		t.Fatalf("detail path should match exact report row")
	}
}

func TestAssignReportStatusesExpandsGroupedRows(t *testing.T) {
	t.Parallel()

	endpoints := []endpointStatus{
		{Method: "GET", Path: "/services/data/v63.0/analytics/reports"},
		{Method: "POST", Path: "/services/data/v63.0/analytics/reports"},
		{Method: "GET", Path: "/services/data/v63.0/analytics/reports/{reportId}"},
		{Method: "PATCH", Path: "/services/data/v63.0/analytics/reports/{reportId}"},
		{Method: "GET", Path: "/services/data/v63.0/analytics/reports/{reportId}/describe"},
		{Method: "GET", Path: "/services/data/v63.0/analytics/dashboards"},
	}
	rows := []reportRow{
		{PathCell: "GET /services/data/v63.0/analytics/reports", Status: statusGreen},
		{PathCell: "POST /services/data/v63.0/analytics/reports", Status: statusGreen},
		{PathCell: "GET/POST/PATCH/DELETE /services/data/v63.0/analytics/reports/{reportId} and GET /services/data/v63.0/analytics/reports/{reportId}/describe", Status: statusNoCoverage},
		{PathCell: "GET /services/data/v63.0/analytics/dashboards", Status: statusGreen},
	}

	assignReportStatuses(endpoints, rows)

	want := []string{
		statusGreen,
		statusGreen,
		statusNoCoverage,
		statusNoCoverage,
		statusNoCoverage,
		statusGreen,
	}
	for i, endpoint := range endpoints {
		if endpoint.Status != want[i] {
			t.Fatalf("endpoint %d got %q, want %q", i, endpoint.Status, want[i])
		}
	}
}

func TestApplyFallbackStatusesUsesCoverageAndPackageStatus(t *testing.T) {
	t.Parallel()

	endpoints := []endpointStatus{
		{Coverage: "todo", TestFile: "query/get_query_test.go"},
		{Coverage: "covered", TestFile: "query/get_query_test.go"},
		{Coverage: "done", TestFile: "query/get_query_more_test.go"},
		{Coverage: "covered", TestFile: "discovery/get_limits_test.go"},
	}
	packageStatuses := map[string]string{
		"github.com/nexuscrm/tests/contract/rest_api/query":     "pass",
		"github.com/nexuscrm/tests/contract/rest_api/discovery": "fail",
	}

	applyFallbackStatuses("rest_api", endpoints, packageStatuses)

	want := []string{
		statusNoCoverage,
		statusGreen,
		statusGreen,
		statusRed,
	}
	for i, endpoint := range endpoints {
		if endpoint.Status != want[i] {
			t.Fatalf("endpoint %d got %q, want %q", i, endpoint.Status, want[i])
		}
	}
}

func TestRenderMarkdownOmitsRunColumn(t *testing.T) {
	t.Parallel()

	markdown := renderMarkdown([]serviceSummary{
		{
			Module:   "Bulk API V2",
			Issue:    issueRef{Number: 337, URL: "https://github.com/pingcap-inc/MetaDrivenPlatform4AI/issues/337"},
			Total:    9,
			Counts:   map[string]int{statusGreen: 9, statusYellow: 0, statusRed: 0, statusNoCoverage: 0, statusNotImplemented: 0},
			PassRate: "100.0% (9/9)",
		},
	})

	if strings.Contains(markdown, "Run |") {
		t.Fatalf("markdown still contains Run column header: %s", markdown)
	}
	if strings.Contains(markdown, "packages passed") {
		t.Fatalf("markdown still contains run status text: %s", markdown)
	}
	if strings.Contains(markdown, "go test -json") {
		t.Fatalf("markdown still references go test -json: %s", markdown)
	}
}

func TestLoadPackageSummaryParsesPlainGoTestOutput(t *testing.T) {
	t.Parallel()

	artifactsDir := t.TempDir()
	logPath := filepath.Join(artifactsDir, "contract-results", "rest_api.log")
	if err := os.MkdirAll(filepath.Dir(logPath), 0o755); err != nil {
		t.Fatalf("mkdir log dir: %v", err)
	}
	logBody := strings.Join([]string{
		"=== RUN   TestGetQuery",
		"--- PASS: TestGetQuery (0.01s)",
		"ok  \tgithub.com/nexuscrm/tests/contract/rest_api/query\t0.021s",
		"?   \tgithub.com/nexuscrm/tests/contract/rest_api/empty\t[no test files]",
		"--- FAIL: TestGetLimits (0.02s)",
		"FAIL",
		"FAIL\tgithub.com/nexuscrm/tests/contract/rest_api/discovery\t0.087s",
	}, "\n")
	if err := os.WriteFile(logPath, []byte(logBody), 0o644); err != nil {
		t.Fatalf("write log: %v", err)
	}

	summary, err := loadPackageSummary(artifactsDir, "rest_api")
	if err != nil {
		t.Fatalf("load package summary: %v", err)
	}

	want := map[string]string{
		"github.com/nexuscrm/tests/contract/rest_api/query":     "pass",
		"github.com/nexuscrm/tests/contract/rest_api/empty":     "skip",
		"github.com/nexuscrm/tests/contract/rest_api/discovery": "fail",
	}
	if len(summary.PackageStatuses) != len(want) {
		t.Fatalf("got %d package statuses, want %d", len(summary.PackageStatuses), len(want))
	}
	for pkg, wantStatus := range want {
		if got := summary.PackageStatuses[pkg]; got != wantStatus {
			t.Fatalf("package %s got %q, want %q", pkg, got, wantStatus)
		}
	}
}

func TestLoadPackageSummaryParsesLegacyJSONArtifact(t *testing.T) {
	t.Parallel()

	artifactsDir := t.TempDir()
	jsonPath := filepath.Join(artifactsDir, "contract-results", "tooling_api.json")
	if err := os.MkdirAll(filepath.Dir(jsonPath), 0o755); err != nil {
		t.Fatalf("mkdir json dir: %v", err)
	}
	jsonBody := strings.Join([]string{
		`{"Action":"pass","Package":"github.com/nexuscrm/tests/contract/tooling_api/query"}`,
		`{"Action":"fail","Package":"github.com/nexuscrm/tests/contract/tooling_api/quick_actions"}`,
		`{"Action":"skip","Package":"github.com/nexuscrm/tests/contract/tooling_api/unused"}`,
	}, "\n")
	if err := os.WriteFile(jsonPath, []byte(jsonBody), 0o644); err != nil {
		t.Fatalf("write json: %v", err)
	}

	summary, err := loadPackageSummary(artifactsDir, "tooling_api")
	if err != nil {
		t.Fatalf("load package summary: %v", err)
	}

	want := map[string]string{
		"github.com/nexuscrm/tests/contract/tooling_api/query":         "pass",
		"github.com/nexuscrm/tests/contract/tooling_api/quick_actions": "fail",
		"github.com/nexuscrm/tests/contract/tooling_api/unused":        "skip",
	}
	for pkg, wantStatus := range want {
		if got := summary.PackageStatuses[pkg]; got != wantStatus {
			t.Fatalf("package %s got %q, want %q", pkg, got, wantStatus)
		}
	}
}
