// Copyright IBM Corp. 2014, 2026
// SPDX-License-Identifier: BUSL-1.1

package statemgr

import (
	"reflect"
	"testing"

	"github.com/davecgh/go-spew/spew"
	"github.com/zclconf/go-cty/cty"

	"github.com/hashicorp/terraform/internal/addrs"
	"github.com/hashicorp/terraform/internal/states"
	"github.com/hashicorp/terraform/internal/states/statefile"
)

// TestFull is a helper for testing full state manager implementations. It
// expects that the given implementation is pre-loaded with a snapshot of the
// result from TestFullInitialState.
//
// If the given state manager also implements PersistentMeta, this function
// will test that the snapshot metadata changes as expected between calls
// to the methods of Persistent.
func TestFull(t *testing.T, s Full) {
	t.Helper()

	if err := s.RefreshState(); err != nil {
		t.Fatalf("err: %s", err)
	}

	// Check that the initial state is correct.
	// These do have different Lineages, but we will replace current below.
	initial := TestFullInitialState()
	if state := s.State(); !state.Equal(initial) {
		t.Fatalf("state does not match expected initial state\n\ngot:\n%s\nwant:\n%s", spew.Sdump(state), spew.Sdump(initial))
	}

	var initialMeta SnapshotMeta
	if sm, ok := s.(PersistentMeta); ok {
		initialMeta = sm.StateSnapshotMeta()
	}

	// Now we've proven that the state we're starting with is an initial
	// state, we'll complete our work here with that state, since otherwise
	// further writes would violate the invariant that we only try to write
	// states that share the same lineage as what was initially written.
	current := s.State()

	// Write a new state and verify that we have it
	current.SetOutputValue(
		addrs.OutputValue{Name: "bar"}.Absolute(addrs.RootModuleInstance),
		cty.StringVal("baz"), false,
	)

	if err := s.WriteState(current); err != nil {
		t.Fatalf("err: %s", err)
	}

	if actual := s.State(); !actual.Equal(current) {
		t.Fatalf("bad:\n%#v\n\n%#v", actual, current)
	}

	// Test persistence
	if err := s.PersistState(nil); err != nil {
		t.Fatalf("err: %s", err)
	}

	// Refresh if we got it
	if err := s.RefreshState(); err != nil {
		t.Fatalf("err: %s", err)
	}

	var newMeta SnapshotMeta
	if sm, ok := s.(PersistentMeta); ok {
		newMeta = sm.StateSnapshotMeta()
		if got, want := newMeta.Lineage, initialMeta.Lineage; got != want {
			t.Errorf("Lineage changed from %q to %q", want, got)
		}
		if after, before := newMeta.Serial, initialMeta.Serial; after == before {
			t.Errorf("Serial didn't change from %d after new module added", before)
		}
	}

	// Same serial
	serial := newMeta.Serial
	if err := s.WriteState(current); err != nil {
		t.Fatalf("err: %s", err)
	}
	if err := s.PersistState(nil); err != nil {
		t.Fatalf("err: %s", err)
	}

	if sm, ok := s.(PersistentMeta); ok {
		newMeta = sm.StateSnapshotMeta()
		if newMeta.Serial != serial {
			t.Fatalf("serial changed after persisting with no changes: got %d, want %d", newMeta.Serial, serial)
		}
	}

	if sm, ok := s.(PersistentMeta); ok {
		newMeta = sm.StateSnapshotMeta()
	}

	// Change the serial
	current = current.DeepCopy()
	current.SetOutputValue(
		addrs.OutputValue{Name: "serialCheck"}.Absolute(addrs.RootModuleInstance),
		cty.StringVal("true"), false,
	)

	if err := s.WriteState(current); err != nil {
		t.Fatalf("err: %s", err)
	}
	if err := s.PersistState(nil); err != nil {
		t.Fatalf("err: %s", err)
	}

	if sm, ok := s.(PersistentMeta); ok {
		oldMeta := newMeta
		newMeta = sm.StateSnapshotMeta()

		if newMeta.Serial <= serial {
			t.Fatalf("serial incorrect after persisting with changes: got %d, want > %d", newMeta.Serial, serial)
		}

		if newMeta.TerraformVersion != oldMeta.TerraformVersion {
			t.Fatalf("TFVersion changed from %s to %s", oldMeta.TerraformVersion, newMeta.TerraformVersion)
		}

		// verify that Lineage doesn't change along with Serial, or during copying.
		if newMeta.Lineage != oldMeta.Lineage {
			t.Fatalf("Lineage changed from %q to %q", oldMeta.Lineage, newMeta.Lineage)
		}
	}

	// Check that State() returns a copy by modifying the copy and comparing
	// to the current state.
	stateCopy := s.State()
	stateCopy.EnsureModule(addrs.RootModuleInstance.Child("another", addrs.NoKey))
	if reflect.DeepEqual(stateCopy, s.State()) {
		t.Fatal("State() should return a copy")
	}

	// our current expected state should also marshal identically to the persisted state
	if !statefile.StatesMarshalEqual(current, s.State()) {
		t.Fatalf("Persisted state altered unexpectedly.\n\ngot:\n%s\nwant:\n%s", spew.Sdump(s.State()), spew.Sdump(current))
	}
}

// TestFullInitialState is a state that should be snapshotted into a
// full state manager before passing it into TestFull.
func TestFullInitialState() *states.State {
	state := states.NewState()
	childMod := state.EnsureModule(addrs.RootModuleInstance.Child("child", addrs.NoKey))
	rAddr := addrs.Resource{
		Mode: addrs.ManagedResourceMode,
		Type: "null_resource",
		Name: "foo",
	}
	providerAddr := addrs.AbsProviderConfig{
		Provider: addrs.NewDefaultProvider(rAddr.ImpliedProvider()),
		Module:   addrs.RootModule,
	}
	childMod.SetResourceProvider(rAddr, providerAddr)

	state.SetOutputValue(
		addrs.OutputValue{Name: "sensitive_output"}.Absolute(addrs.RootModuleInstance),
		cty.StringVal("it's a secret"), true,
	)
	state.SetOutputValue(
		addrs.OutputValue{Name: "nonsensitive_output"}.Absolute(addrs.RootModuleInstance),
		cty.StringVal("hello, world!"), false,
	)

	return state
}
