package analytics

import (
	"bytes"
	"context"
	"encoding/json"
	"flag"
	"os"
	"path/filepath"
	"testing"

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

var updateGoldens = flag.Bool("update", false, "update CRT golden expected.json files in place")

// goldensFakeMetadata returns a fake metadata lookup with just enough schemas
// to satisfy the 10 hand-picked golden CRTs under testdata/crt_goldens.
// Additions here should stay focused on those CRTs — broader schema
// enumeration belongs in the metadata service tests, not in the synthesizer
// golden suite.
func goldensFakeMetadata() *fakeMetadata {
	md := newFakeMetadata()

	// Base objects with no children used by the goldens.
	md.addObject("", "FlowOrchestrationStageInstance", "Id", "Name")
	md.addObject("", "awsapn__Sync_Log_Detail__c", "Id", "Name")

	// Lead + Account + Opportunity roots.
	md.addObject("", "Lead", "Id", "Name")
	md.addObject("", "Account", "Id", "Name")
	md.addObject("", "Opportunity", "Id", "Name")
	md.addObject("", "Campaign", "Id", "Name")
	md.addObject("", "ForecastingItem", "Id", "Name")
	md.addObject("", "pqcrush__Account_Plan__c", "Id", "Name")

	// Children referenced by the golden join trees.
	md.addObject("Campaign", "CampaignMember", "Id", "Status", "CampaignId->Campaign:CampaignMembers")
	md.addObject("Lead", "CampaignMember_Lead", "Id", "LeadId->Lead:CampaignMembers")

	md.addObject("Account", "Task", "Id", "AccountId->Account:Activities")
	md.addObject("Account", "Monthly_ARR__c", "Id", "AccountId->Account:Monthly_ARRs__r")

	md.addObject("Opportunity", "Elvance__Elvance_Scorecard__c", "Id",
		"OpportunityId->Opportunity:Elvance__Elvance_Scorecards__r")
	md.addObject("Elvance__Elvance_Scorecard__c", "Elvance__Feature_Gap_Entry__c", "Id",
		"ScorecardId->Elvance__Elvance_Scorecard__c:Elvance__Feature_Gap_Entries__r")

	md.addObject("ForecastingItem", "ForecastingItemHistory", "Id",
		"ParentId->ForecastingItem:ForecastingItem__hd")

	md.addObject("pqcrush__Account_Plan__c", "pqcrush__White_Space__c", "Id",
		"PlanId->pqcrush__Account_Plan__c:pqcrush__White_Spaces__r")
	md.addObject("pqcrush__White_Space__c", "pqcrush__White_Space_Cell__c", "Id",
		"SpaceId->pqcrush__White_Space__c:pqcrush__White_Space_Cells__r")
	md.addObject("pqcrush__White_Space_Cell__c", "pqcrush__Cross_Sell_Data_Type_Association__c", "Id",
		"CellId->pqcrush__White_Space_Cell__c:pqcrush__Cross_Sell_Data_Type_Associations__r")

	return md
}

func TestCRTGoldens(t *testing.T) {
	dir := "testdata/crt_goldens"
	entries, err := os.ReadDir(dir)
	require.NoError(t, err)

	md := goldensFakeMetadata()
	synth := newCRTSynthesizerWithLookup(md, nil)

	var ran int
	for _, e := range entries {
		if !e.IsDir() {
			continue
		}
		slug := e.Name()
		t.Run(slug, func(t *testing.T) {
			inputPath := filepath.Join(dir, slug, "input.json")
			raw, err := os.ReadFile(inputPath)
			require.NoError(t, err)

			var in models.SystemReportType
			require.NoError(t, json.Unmarshal(raw, &in))

			tmpl, warnings := synth.Synthesize(context.Background(), &in)

			got := map[string]any{
				"template": tmpl,
				"warnings": warnings,
			}
			gotJSON, err := json.MarshalIndent(got, "", "  ")
			require.NoError(t, err)
			gotJSON = append(gotJSON, '\n')

			expectedPath := filepath.Join(dir, slug, "expected.json")
			if *updateGoldens {
				require.NoError(t, os.WriteFile(expectedPath, gotJSON, 0o644))
				return
			}
			wantJSON, err := os.ReadFile(expectedPath)
			if err != nil {
				t.Fatalf("missing expected.json for %s — re-run with -update: %v", slug, err)
			}
			if !bytes.Equal(gotJSON, wantJSON) {
				t.Fatalf("golden mismatch for %s\n--- want ---\n%s\n--- got ---\n%s", slug, string(wantJSON), string(gotJSON))
			}
		})
		ran++
	}
	if ran == 0 {
		t.Fatal("no golden fixtures found under testdata/crt_goldens")
	}
}
