package boundary_test

import (
	"bytes"
	"encoding/json"
	"io"
	"os"
	"path/filepath"
	"strings"
	"testing"
)

const runtimeMetadataClosureManifest = "docs/refactor/serviceification/runtime-metadata-closure-p7a.json"

type runtimeMetadataClosure struct {
	Schema                   string                       `json:"schema"`
	EvidenceRevision         string                       `json:"evidence_revision"`
	AlignmentRevision        string                       `json:"alignment_revision"`
	Scope                    runtimeMetadataClosureScope  `json:"scope"`
	Classifications          []string                     `json:"classifications"`
	CompositionRootCalls     []runtimeMetadataClosureCall `json:"composition_root_calls"`
	ProductionAssemblerCalls []runtimeMetadataClosureCall `json:"production_assembler_calls"`
	ReadPaths                []runtimeMetadataClosureRead `json:"read_paths"`
	ProcessGlobalState       []runtimeMetadataClosureRead `json:"process_global_state"`
	RefreshInvalidationPaths []runtimeMetadataClosureRead `json:"refresh_and_invalidation_paths"`
	RuntimeMetadataViewFacts []string                     `json:"runtime_metadata_view_facts"`
	P7CConsumerSwitches      []string                     `json:"p7c_consumer_switches"`
	P7CUnreachableEdges      []string                     `json:"p7c_unreachable_edges"`
	NonServingGuard          map[string]bool              `json:"non_serving_guard"`
}

type runtimeMetadataClosureScope struct {
	ProductionCandidateEntrypoint  string   `json:"production_candidate_entrypoint"`
	ServingOperations              []string `json:"serving_operations"`
	CurrentIndependentCapabilities []string `json:"current_independent_capabilities"`
	C0FirstProductionRoute         string   `json:"c0_first_production_route"`
	C0CapabilityInCurrentClosure   bool     `json:"c0_capability_in_current_independent_closure"`
	CurrentCommandEntrypoint       string   `json:"current_command_entrypoint"`
	CurrentCommandServes           bool     `json:"current_command_serves"`
	LegacyMonolithIncluded         bool     `json:"legacy_monolith_included"`
}

type runtimeMetadataClosureCall struct {
	Call  string `json:"call"`
	Count int    `json:"count"`
}

type runtimeMetadataClosureRead struct {
	ID             string `json:"id"`
	Phase          string `json:"phase"`
	Owner          string `json:"owner"`
	Accessor       string `json:"accessor"`
	Classification string `json:"classification"`
	SourceFile     string `json:"source_file"`
	SourceAnchor   string `json:"source_anchor"`
	Note           string `json:"note"`
}

func TestRuntimeMetadataClosureManifestIsCompleteAndAnchored(t *testing.T) {
	root := repoRoot(t)
	manifest := loadRuntimeMetadataClosure(t, root)

	if manifest.Schema != "nexuscrm.runtime-metadata-closure.p7a/v2" {
		t.Fatalf("manifest schema = %q", manifest.Schema)
	}
	if !validCommitSHA(manifest.EvidenceRevision) {
		t.Fatalf("evidence revision = %q, want full commit SHA", manifest.EvidenceRevision)
	}
	if !validCommitSHA(manifest.AlignmentRevision) {
		t.Fatalf("alignment revision = %q, want full commit SHA", manifest.AlignmentRevision)
	}
	if manifest.Scope.LegacyMonolithIncluded {
		t.Fatalf("inventory must exclude the legacy monolith: %#v", manifest.Scope)
	}
	if manifest.Scope.ProductionCandidateEntrypoint != "backend/internal/runtimeapi.AssembleProduction" ||
		!sameStrings(manifest.Scope.ServingOperations, []string{
			"backend/internal/runtimeapi.RecordsServer.EvaluateRecordAccess",
			"backend/internal/runtimeapi.RecordsServer.ReadSelectedRoot",
		}) ||
		!sameStrings(manifest.Scope.CurrentIndependentCapabilities, []string{
			"runtime.records.evaluate-access.v1", "runtime.records.read-selected-root.v1",
		}) ||
		manifest.Scope.C0FirstProductionRoute != "POST /services/data/:version/ui-api/record-access" ||
		!manifest.Scope.C0CapabilityInCurrentClosure {
		t.Fatalf("scope entrypoints changed without an inventory revision: %#v", manifest.Scope)
	}

	allowedClassifications := make(map[string]struct{}, len(manifest.Classifications))
	for _, classification := range manifest.Classifications {
		if strings.TrimSpace(classification) == "" {
			t.Fatal("manifest contains blank classification")
		}
		allowedClassifications[classification] = struct{}{}
	}
	if len(manifest.Classifications) != 5 || len(allowedClassifications) != 5 {
		t.Fatalf("classifications = %v, want the five P7a classes", manifest.Classifications)
	}

	seenIDs := make(map[string]struct{}, len(manifest.ReadPaths)+len(manifest.ProcessGlobalState)+len(manifest.RefreshInvalidationPaths))
	seenClasses := make(map[string]bool, len(allowedClassifications))
	for group, reads := range map[string][]runtimeMetadataClosureRead{
		"read_paths":                     manifest.ReadPaths,
		"process_global_state":           manifest.ProcessGlobalState,
		"refresh_and_invalidation_paths": manifest.RefreshInvalidationPaths,
	} {
		if len(reads) == 0 {
			t.Fatalf("%s must be non-empty", group)
		}
		for _, read := range reads {
			if _, duplicate := seenIDs[read.ID]; duplicate || strings.TrimSpace(read.ID) == "" {
				t.Fatalf("duplicate or blank inventory id %q", read.ID)
			}
			seenIDs[read.ID] = struct{}{}
			if _, ok := allowedClassifications[read.Classification]; !ok {
				t.Fatalf("inventory entry %s has unknown classification %q", read.ID, read.Classification)
			}
			seenClasses[read.Classification] = true
			if read.Phase == "" || read.Owner == "" || read.Accessor == "" || read.Note == "" || read.SourceFile == "" || read.SourceAnchor == "" {
				t.Fatalf("inventory entry %s is incomplete: %#v", read.ID, read)
			}
			path := filepath.Join(root, filepath.FromSlash(read.SourceFile))
			body, err := os.ReadFile(path)
			if err != nil {
				t.Fatalf("read source for %s: %v", read.ID, err)
			}
			// The P7a inventory is historical input to the D1 cutover. The
			// independent receipt source was intentionally made unreachable by
			// D1; current serving guards below prove the replacement.
			if read.ID != "request-independent-receipt-source" && !strings.Contains(string(body), read.SourceAnchor) {
				t.Fatalf("inventory entry %s lost source anchor %q in %s; update the inventory before changing the closure", read.ID, read.SourceAnchor, read.SourceFile)
			}
		}
	}
	for classification := range allowedClassifications {
		if !seenClasses[classification] {
			t.Fatalf("classification %q has no inventoried read", classification)
		}
	}

	for name, values := range map[string][]string{
		"runtime_metadata_view_facts": manifest.RuntimeMetadataViewFacts,
		"p7c_consumer_switches":       manifest.P7CConsumerSwitches,
		"p7c_unreachable_edges":       manifest.P7CUnreachableEdges,
	} {
		if len(values) == 0 {
			t.Fatalf("%s must be finite and non-empty", name)
		}
		seen := make(map[string]struct{}, len(values))
		for _, value := range values {
			value = strings.TrimSpace(value)
			if value == "" {
				t.Fatalf("%s contains a blank entry", name)
			}
			if _, duplicate := seen[value]; duplicate {
				t.Fatalf("%s contains duplicate entry %q", name, value)
			}
			seen[value] = struct{}{}
		}
	}
	wantNonServingGuards := []string{
		"p7b_must_not_add_production_snapshot_import_to_runtimeapi_or_runtimeassembly",
		"p7b_must_not_add_repository_fallback",
		"p7b_must_not_change_current_command_entrypoint",
		"p7b_must_not_make_any_engine_consumer_selectable",
		"p7b_must_publish_only_after_full_parity",
	}
	if len(manifest.NonServingGuard) != len(wantNonServingGuards) {
		t.Fatalf("non-serving guards = %v, want exactly %v", manifest.NonServingGuard, wantNonServingGuards)
	}
	for _, name := range wantNonServingGuards {
		if !manifest.NonServingGuard[name] {
			t.Fatalf("non-serving guard %q must be present and true", name)
		}
	}
}

func validCommitSHA(value string) bool {
	return len(value) == 40 && strings.Trim(value, "0123456789abcdef") == ""
}

func sameStrings(left, right []string) bool {
	if len(left) != len(right) {
		return false
	}
	for i := range left {
		if left[i] != right[i] {
			return false
		}
	}
	return true
}

func TestRuntimeMetadataClosurePinsCurrentCompositionRoots(t *testing.T) {
	root := repoRoot(t)
	command := readFile(t, filepath.Join(root, "backend", "cmd", "runtime-api", "main.go"))
	if !strings.Contains(command, "runtimeproduction.Assemble") {
		t.Fatal("runtime-api command does not use the explicit D1 serving composition")
	}
	for _, required := range []string{
		`len(args) == 1 && args[0] == "bootstrap"`,
		"runtimeconfig.LoadAPIBootstrap",
		"runtimeapi.AssembleNonServingBootstrap",
		"if len(args) != 0",
	} {
		if !strings.Contains(command, required) {
			t.Fatalf("runtime-api command lost explicit deployment-only bootstrap fence %q", required)
		}
	}
	assembly := readFile(t, filepath.Join(root, "backend", "internal", "runtimeassembly", "records_read.go"))
	for _, required := range []string{"NewServingRecordsReadRuntime", "metadata.NewRuntimeMetadataService", "UsesRequestBoundRuntimeView"} {
		if !strings.Contains(assembly, required) {
			t.Fatalf("D1 serving assembly lost %q", required)
		}
	}
	production := readFile(t, filepath.Join(root, "backend", "internal", "runtimeproduction", "assemble.go"))
	for _, required := range []string{"CatalogServingSource", "NewServingState", "servingState.Reconcile", "AssembleProductionWithConnection"} {
		if !strings.Contains(production, required) {
			t.Fatalf("D1 production composition lost %q", required)
		}
	}
}

func loadRuntimeMetadataClosure(t *testing.T, root string) runtimeMetadataClosure {
	t.Helper()
	data, err := os.ReadFile(filepath.Join(root, filepath.FromSlash(runtimeMetadataClosureManifest)))
	if err != nil {
		t.Fatalf("read runtime metadata closure manifest: %v", err)
	}
	var manifest runtimeMetadataClosure
	decoder := json.NewDecoder(bytes.NewReader(data))
	decoder.DisallowUnknownFields()
	if err := decoder.Decode(&manifest); err != nil {
		t.Fatalf("decode runtime metadata closure manifest: %v", err)
	}
	if err := decoder.Decode(&struct{}{}); err != io.EOF {
		t.Fatalf("runtime metadata closure manifest has trailing content: %v", err)
	}
	return manifest
}
