package metadata

import (
	"testing"

	"github.com/nexuscrm/shared/pkg/constants"
	"github.com/nexuscrm/shared/pkg/models"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

// ---------------------------------------------------------------------------
// extractFieldGroupPrefix
// ---------------------------------------------------------------------------

func TestExtractFieldGroupPrefix(t *testing.T) {
	tests := []struct {
		apiName string
		want    string
	}{
		{"ARR_Amount__c", "ARR"},
		{"Partner_Name__c", "Partner"},
		{"AWS_Account_ID__c", "AWS"},
		{"ACV_Amount_USD__c", "ACV"},
		{"Source_Database_Name__c", "Source"},
		{"Tags__c", ""},     // single-word custom field — no prefix
		{"Name", ""},        // standard field
		{"AccountId", ""},   // standard field
		{"CreatedDate", ""}, // standard field
		{"__c", ""},         // degenerate: only suffix
		{"X__c", ""},        // single char, no underscore before __c
		{"A_B__c", "A"},     // minimal valid prefix
		{"Infrastructure_Status__c", "Infrastructure"},
	}
	for _, tt := range tests {
		t.Run(tt.apiName, func(t *testing.T) {
			got := extractFieldGroupPrefix(tt.apiName)
			assert.Equal(t, tt.want, got)
		})
	}
}

// ---------------------------------------------------------------------------
// humanizeGroupLabel
// ---------------------------------------------------------------------------

func TestHumanizeGroupLabel(t *testing.T) {
	tests := []struct {
		prefix string
		want   string
	}{
		{"ARR", "ARR"},
		{"AWS", "AWS"},
		{"ACV", "ACV"},
		{"TCV", "TCV"},
		{"Partner", "Partner"},
		{"source", "Source"},
		{"INFRASTRUCTURE", "Infrastructure"},
		{"", ""},
	}
	for _, tt := range tests {
		t.Run(tt.prefix, func(t *testing.T) {
			got := humanizeGroupLabel(tt.prefix)
			assert.Equal(t, tt.want, got)
		})
	}
}

// ---------------------------------------------------------------------------
// generateSmartLayout — prefix grouping
// ---------------------------------------------------------------------------

func TestGenerateSmartLayout_PrefixGrouping(t *testing.T) {
	// Build a schema with standard fields + custom fields sharing prefixes
	fields := []models.FieldMetadata{
		{APIName: "Name", Label: "Name", IsNameField: true},
		{APIName: "StageName", Label: "Stage"},
		{APIName: "Amount", Label: "Amount", Required: true},
		{APIName: "OwnerId", Label: "Owner", Type: constants.FieldTypeReference},
		{APIName: "Description", Label: "Description", Type: constants.FieldTypeTextarea},
		{APIName: "CreatedById", Label: "Created By", IsSystem: true},
		{APIName: "LastModifiedById", Label: "Last Modified By", IsSystem: true},
		// ARR prefix group (3 fields → qualifies)
		{APIName: "ARR_Amount__c", Label: "ARR Amount"},
		{APIName: "ARR_Type__c", Label: "ARR Type"},
		{APIName: "ARR_Start_Date__c", Label: "ARR Start Date"},
		// Partner prefix group (3 fields → qualifies)
		{APIName: "Partner_Name__c", Label: "Partner Name"},
		{APIName: "Partner_Type__c", Label: "Partner Type"},
		{APIName: "Partner_Margin__c", Label: "Partner Margin"},
		// AWS prefix group (3 fields → qualifies)
		{APIName: "AWS_Account_ID__c", Label: "AWS Account ID"},
		{APIName: "AWS_Region__c", Label: "AWS Region"},
		{APIName: "AWS_Status__c", Label: "AWS Status"},
		// Small group (2 fields → below threshold, stays in Additional Details)
		{APIName: "Tiny_One__c", Label: "Tiny One"},
		{APIName: "Tiny_Two__c", Label: "Tiny Two"},
		// Ungrouped custom field (no prefix)
		{APIName: "Tags__c", Label: "Tags"},
		// Ungrouped standard detail field
		{APIName: "FiscalYear", Label: "Fiscal Year"},
	}

	obj := &models.ObjectMetadata{APIName: "Opportunity", Fields: fields}
	layout := generateSmartLayout("Opportunity", obj)

	require.NotNil(t, layout)

	// Collect section labels
	var labels []string
	for _, s := range layout.Sections {
		labels = append(labels, s.Label)
	}

	// Expect: Opportunity Information, ARR, AWS, Partner, Description, Additional Information, System Information
	// (Phase 2: standard objects get object-specific section labels)
	assert.Contains(t, labels, "Opportunity Information")
	assert.Contains(t, labels, "ARR")
	assert.Contains(t, labels, "AWS")
	assert.Contains(t, labels, "Partner")
	assert.Contains(t, labels, "Description")
	assert.Contains(t, labels, "Additional Information", "ungrouped fields should remain in Additional Information")
	assert.Contains(t, labels, constants.SectionLabelSystemInfo)

	// Verify prefix sections appear in alphabetical order and before Description
	arrIdx, awsIdx, partnerIdx, descIdx, detailIdx := -1, -1, -1, -1, -1
	for i, l := range labels {
		switch l {
		case "ARR":
			arrIdx = i
		case "AWS":
			awsIdx = i
		case "Partner":
			partnerIdx = i
		case "Description":
			descIdx = i
		case "Additional Information":
			detailIdx = i
		}
	}
	assert.True(t, arrIdx < awsIdx, "ARR should come before AWS (alphabetical)")
	assert.True(t, awsIdx < partnerIdx, "AWS should come before Partner (alphabetical)")
	assert.True(t, partnerIdx < descIdx, "prefix sections should come before Description")
	assert.True(t, descIdx < detailIdx, "Description should come before Additional Information")

	// Verify ARR section has exactly 3 fields
	for _, s := range layout.Sections {
		if s.Label == "ARR" {
			assert.Len(t, s.Fields, 3)
		}
	}

	// Verify Additional Information contains the below-threshold and ungrouped fields
	for _, s := range layout.Sections {
		if s.Label == "Additional Information" {
			assert.Contains(t, s.Fields, "Tiny_One__c")
			assert.Contains(t, s.Fields, "Tiny_Two__c")
			assert.Contains(t, s.Fields, "Tags__c")
			assert.Contains(t, s.Fields, "FiscalYear")
			// Should NOT contain fields that were grouped
			assert.NotContains(t, s.Fields, "ARR_Amount__c")
			assert.NotContains(t, s.Fields, "Partner_Name__c")
		}
	}
}

func TestGenerateSmartLayout_NoCustomFields(t *testing.T) {
	// Standard fields only — should produce the classic 5-section layout
	fields := []models.FieldMetadata{
		{APIName: "Name", Label: "Name", IsNameField: true},
		{APIName: "Amount", Label: "Amount", Required: true},
		{APIName: "Description", Label: "Description", Type: constants.FieldTypeTextarea},
		{APIName: "BillingStreet", Label: "Billing Street"},
		{APIName: "BillingCity", Label: "Billing City"},
		{APIName: "CreatedById", Label: "Created By", IsSystem: true},
		{APIName: "FiscalYear", Label: "Fiscal Year"},
	}

	obj := &models.ObjectMetadata{APIName: "TestObj", Fields: fields}
	layout := generateSmartLayout("TestObj", obj)

	var labels []string
	for _, s := range layout.Sections {
		labels = append(labels, s.Label)
	}

	// No prefix-based sections expected
	assert.Equal(t, []string{
		constants.SectionLabelInformation,
		constants.SectionLabelAddress,
		constants.SectionLabelDescription,
		constants.SectionLabelDetails,
		constants.SectionLabelSystemInfo,
	}, labels)
}

func TestGenerateSmartLayout_VersionIs8(t *testing.T) {
	assert.Equal(t, 8, currentGenerationVersion, "generation version should be 8 (Order layouts include archived order form fields by default)")
}
