package batch

import (
	"testing"

	"sub2api-cn-relay-manager/internal/store/sqlite"
)

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

	t.Run("run summary exposes recent warnings and warning badge label", func(t *testing.T) {
		t.Parallel()

		run := sqlite.ImportRun{
			RunID:          "run-1",
			State:          string(RunStateCompletedWithWarnings),
			Mode:           "partial",
			AccessMode:     "subscription",
			TotalItems:     2,
			CompletedItems: 2,
			ActiveItems:    1,
			DegradedItems:  1,
			BrokenItems:    0,
			WarningItems:   1,
			StartedAt:      "2026-05-22T12:20:00+08:00",
			FinishedAt:     "2026-05-22T12:20:07+08:00",
		}

		view := ProjectRunSummary(run)
		if view.StateBadge.Label != "warning" {
			t.Fatalf("StateBadge.Label = %q, want warning", view.StateBadge.Label)
		}
		if len(view.RecentWarnings) != 1 {
			t.Fatalf("len(RecentWarnings) = %d, want 1", len(view.RecentWarnings))
		}
		if view.RecentWarnings[0] != "该批次包含 1 条 advisory item，建议检查 capability profile 与 retry 轨迹" {
			t.Fatalf("RecentWarnings[0] = %q, want canonical warning copy", view.RecentWarnings[0])
		}
	})

	t.Run("item summary projection maps warning copy and reuse badges", func(t *testing.T) {
		t.Parallel()

		item := sqlite.ImportRunItem{
			ItemID:                "item-1",
			RunID:                 "run-1",
			BaseURL:               "https://kimi.example.com/v1",
			ProviderID:            "kimi-a7m-7d7ac291",
			APIKeyFingerprint:     "sha256:8d8c4b5f",
			RequestedModelsJSON:   `["kimi-k2.6"]`,
			CanonicalFamiliesJSON: `["kimi-k2.6"]`,
			ResolvedSmokeModel:    "kimi-k2.6",
			CurrentStage:          string(ItemStageDone),
			ConfirmationStatus:    string(ConfirmationAdvisory),
			AccessStatus:          string(AccessStatusActive),
			MatchedAccountState:   string(MatchedAccountStateActive),
			AccountResolution:     string(AccountResolutionReused),
			ProvisionReused:       true,
			RetryCount:            2,
			LastRetryAt:           "2026-05-22T12:20:05+08:00",
			AdvisoryMessagesJSON:  `["responses_unsupported_but_chat_ok","gateway_warmup_retry_succeeded"]`,
			LastErrorStage:        string(ItemStageConfirm),
			LastError:             "API returned 403: Forbidden",
		}

		view := ProjectItemSummary(item)
		if len(view.Badges) < 3 {
			t.Fatalf("len(Badges) = %d, want at least 3", len(view.Badges))
		}
		if !hasBadge(view.Badges, "reused", "reused") {
			t.Fatalf("Badges = %#v, want reused badge", view.Badges)
		}
		if !hasBadge(view.Badges, "matched_account_state", "已启用") {
			t.Fatalf("Badges = %#v, want matched account state badge", view.Badges)
		}
		if !hasBadge(view.Badges, "account_resolution", "复用") {
			t.Fatalf("Badges = %#v, want account resolution badge", view.Badges)
		}
		if len(view.AdvisoryMessages) != 2 {
			t.Fatalf("len(AdvisoryMessages) = %d, want 2", len(view.AdvisoryMessages))
		}
		if view.AdvisoryMessages[0] != "该上游不支持 /v1/responses，系统已自动回退到 /v1/chat/completions" {
			t.Fatalf("AdvisoryMessages[0] = %q, want responses fallback copy", view.AdvisoryMessages[0])
		}
		if view.AdvisoryMessages[1] != "初次调度出现 no available accounts，短暂重试后已恢复" {
			t.Fatalf("AdvisoryMessages[1] = %q, want warmup retry copy", view.AdvisoryMessages[1])
		}
	})

	t.Run("item detail projection exposes capability profile and event trail", func(t *testing.T) {
		t.Parallel()

		item := sqlite.ImportRunItem{
			ItemID:                "item-2",
			RunID:                 "run-1",
			BaseURL:               "https://kimi.example.com/v1",
			ProviderID:            "kimi-a7m-7d7ac291",
			APIKeyFingerprint:     "sha256:8d8c4b5f",
			RequestedModelsJSON:   `["kimi-k2.6"]`,
			RawModelsJSON:         `["kimi-k2.6"]`,
			NormalizedModelsJSON:  `["kimi-k2.6"]`,
			CanonicalFamiliesJSON: `["kimi-k2.6"]`,
			RecommendedModelsJSON: `[]`,
			ResolvedSmokeModel:    "kimi-k2.6",
			CurrentStage:          string(ItemStageDone),
			ConfirmationStatus:    string(ConfirmationAdvisory),
			AccessStatus:          string(AccessStatusActive),
			MatchedAccountState:   string(MatchedAccountStateDeprecated),
			AccountResolution:     string(AccountResolutionReactivated),
			ProvisionReused:       true,
			ReusedFromProviderID:  "kimi-a7m-7d7ac291",
			ReusedFromAccountID:   int64Ptr(4),
			RetryCount:            2,
			LastRetryAt:           "2026-05-22T12:20:05+08:00",
			ChannelID:             int64Ptr(12),
			AccountID:             int64Ptr(4),
			AdvisoryMessagesJSON:  `["responses_unsupported_but_chat_ok","initial_probe_race_expected"]`,
			LastErrorStage:        string(ItemStageConfirm),
			LastError:             "API returned 403: Forbidden",
			CapabilityProfileJSON: `{"transport_profile":{"supports_openai_models":true,"supports_openai_chat_completions":true,"supports_openai_responses":false,"supports_anthropic_messages":false,"auth_style":"bearer","model_id_style":"canonical","known_advisories":["responses_unsupported_but_chat_ok","initial_probe_race_expected"]},"model_profiles":[{"raw_model_id":"kimi-k2.6","normalized_model_id":"kimi-k2.6","canonical_model_family":"kimi-k2.6","supports_stream":"true","supports_tools":"unknown","supports_reasoning_fields":"unknown","smoke_chat_ok":true}]}`,
		}
		events := []sqlite.ImportRunItemEvent{
			{
				EventID:     "evt-01",
				RunID:       "run-1",
				ItemID:      "item-2",
				EventType:   "retry_scheduled",
				Stage:       string(ItemStageConfirm),
				Attempt:     1,
				Message:     "initial 503 no available accounts, retry scheduled",
				PayloadJSON: `{"delay_ms":500}`,
				CreatedAt:   "2026-05-22T12:20:04+08:00",
			},
		}

		view, err := ProjectItemDetail(item, events)
		if err != nil {
			t.Fatalf("ProjectItemDetail() error = %v", err)
		}
		if view.ReusedFromProviderID != "kimi-a7m-7d7ac291" {
			t.Fatalf("ReusedFromProviderID = %q, want kimi-a7m-7d7ac291", view.ReusedFromProviderID)
		}
		if view.ReusedFromAccountID == nil || *view.ReusedFromAccountID != 4 {
			t.Fatalf("ReusedFromAccountID = %#v, want 4", view.ReusedFromAccountID)
		}
		if len(view.Events) != 1 || view.Events[0].EventType != "retry_scheduled" {
			t.Fatalf("Events = %#v, want retry event trail", view.Events)
		}
		if !view.CapabilityProfile.TransportProfile.SupportsOpenAIChatCompletions {
			t.Fatal("CapabilityProfile.TransportProfile.SupportsOpenAIChatCompletions = false, want true")
		}
		if len(view.CapabilityProfile.ModelProfiles) != 1 || view.CapabilityProfile.ModelProfiles[0].CanonicalModelFamily != "kimi-k2.6" {
			t.Fatalf("CapabilityProfile.ModelProfiles = %#v, want canonical model family", view.CapabilityProfile.ModelProfiles)
		}
		if !hasBadge(view.Badges, "account_resolution", "已快速启用") {
			t.Fatalf("Badges = %#v, want reactivated badge", view.Badges)
		}
		if !hasBadge(view.Badges, "matched_account_state", "已弃用") {
			t.Fatalf("Badges = %#v, want deprecated badge", view.Badges)
		}
	})
}

func hasBadge(badges []ProjectionBadge, kind, label string) bool {
	for _, badge := range badges {
		if badge.Kind == kind && badge.Label == label {
			return true
		}
	}
	return false
}
