package tenantoverlay

import (
	"encoding/json"
	"testing"

	"github.com/nexuscrm/backend/internal/features/automation/autonumber"
)

// TestTenantAutoNumberFormatSeeds_QuoteNameTokenRefs pins Quote.Name's
// multi-chain TokenRefsJSON: the engine must be able to render
// `{Account.BillingCountryCode}` via
// `OpportunityId → Opportunity.AccountId → Account.BillingCountryCode`
// when the Quote has an Opportunity but no direct AccountId (the common
// case for quotes sourced from opportunities).
//
// This used to live in controlplane/packs; moved here per issue #1609
// because Quote.Name's TokenRefsJSON dereferences the tenant field
// `Account_Country_Code__c` and the whole seed now lives in the
// PingCAP tenant package.
func TestTenantAutoNumberFormatSeeds_QuoteNameTokenRefs(t *testing.T) {
	var quote *AutoNumberFormatSeedsEntry
	seeds := readAutoNumberOverlayForTest(t).AutoNumberFormatSeeds
	for i := range seeds {
		s := seeds[i]
		if s.ObjectName == "Quote" && s.FieldApiName == "Name" {
			quote = &AutoNumberFormatSeedsEntry{
				ObjectName:    s.ObjectName,
				FieldApiName:  s.FieldApiName,
				TokenRefsJSON: s.TokenRefsJSON,
			}
			break
		}
	}
	if quote == nil {
		t.Fatal("Quote.Name seed missing from tenant AutoNumberFormatSeeds")
	}
	if quote.TokenRefsJSON == "" {
		t.Fatal("Quote.Name TokenRefsJSON unexpectedly empty — regen scripts/gen")
	}

	var refs []autonumber.CrossRecordRef
	if err := json.Unmarshal([]byte(quote.TokenRefsJSON), &refs); err != nil {
		t.Fatalf("unmarshal Quote.Name TokenRefsJSON: %v\nraw=%q", err, quote.TokenRefsJSON)
	}
	if len(refs) != 1 {
		t.Fatalf("expected exactly 1 CrossRecordRef for Quote.Name, got %d", len(refs))
	}
	ref := refs[0]
	if ref.TokenLiteral != "{Account.BillingCountryCode}" {
		t.Errorf("TokenLiteral: got %q, want %q", ref.TokenLiteral, "{Account.BillingCountryCode}")
	}
	if ref.TargetField != "BillingCountryCode" {
		t.Errorf("TargetField: got %q, want %q", ref.TargetField, "BillingCountryCode")
	}
	if ref.TargetObject != "Account" {
		t.Errorf("TargetObject: got %q, want %q", ref.TargetObject, "Account")
	}
	if ref.DirectField != "Account_Country_Code__c" {
		t.Errorf("DirectField: got %q, want %q", ref.DirectField, "Account_Country_Code__c")
	}
	if len(ref.FkChains) != 2 {
		t.Fatalf("expected 2 FkChains (Opportunity hop + direct Account), got %d", len(ref.FkChains))
	}
	// First chain: OpportunityId → Opportunity.AccountId → Account.BillingCountryCode
	if len(ref.FkChains[0]) != 2 {
		t.Errorf("FkChains[0] depth: got %d, want 2", len(ref.FkChains[0]))
	} else {
		step0, step1 := ref.FkChains[0][0], ref.FkChains[0][1]
		if step0.FK != "OpportunityId" || step0.TargetObject != "Opportunity" {
			t.Errorf("FkChains[0][0]: got %+v, want {FK:OpportunityId, TargetObject:Opportunity, ...}", step0)
		}
		if step1.FK != "AccountId" || step1.TargetObject != "Account" ||
			step1.TargetField != "BillingCountryCode" {
			t.Errorf("FkChains[0][1]: got %+v, want AccountId→Account.BillingCountryCode", step1)
		}
	}
	// Second chain: AccountId → Account.BillingCountryCode
	if len(ref.FkChains[1]) != 1 {
		t.Errorf("FkChains[1] depth: got %d, want 1", len(ref.FkChains[1]))
	} else {
		step := ref.FkChains[1][0]
		if step.FK != "AccountId" || step.TargetObject != "Account" ||
			step.TargetField != "BillingCountryCode" {
			t.Errorf("FkChains[1][0]: got %+v, want AccountId→Account.BillingCountryCode", step)
		}
	}

	// Canonicalize round-trips: the writer relies on byte equality after
	// CanonicalizeTokenRefs to produce idempotent UPDATEs.
	var generic any
	if err := json.Unmarshal([]byte(quote.TokenRefsJSON), &generic); err != nil {
		t.Fatalf("unmarshal generic: %v", err)
	}
	canonical, err := autonumber.CanonicalizeTokenRefs(generic)
	if err != nil {
		t.Fatalf("CanonicalizeTokenRefs: %v", err)
	}
	if len(canonical) == 0 {
		t.Fatal("canonical form unexpectedly empty")
	}
}

// AutoNumberFormatSeedsEntry is a test-only projection of the fields
// asserted above. The canonical struct lives in packs.AutoNumberFormatSeed;
// duplicating the minimal shape here keeps this test free of a packs import.
type AutoNumberFormatSeedsEntry struct {
	ObjectName    string
	FieldApiName  string
	TokenRefsJSON string
}
