// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package tfjson

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"

	"github.com/hashicorp/go-version"
	"github.com/zclconf/go-cty/cty"
)

// StateFormatVersionConstraints defines the versions of the JSON state format
// that are supported by this package.
var StateFormatVersionConstraints = ">= 0.1, < 2.0"

// State is the top-level representation of a Terraform state.
type State struct {
	// useJSONNumber opts into the behavior of calling
	// json.Decoder.UseNumber prior to decoding the state, which turns
	// numbers into json.Numbers instead of float64s. Set it using
	// State.UseJSONNumber.
	useJSONNumber bool

	// The version of the state format. This should always match the
	// StateFormatVersion constant in this package, or else am
	// unmarshal will be unstable.
	FormatVersion string `json:"format_version,omitempty"`

	// The Terraform version used to make the state.
	TerraformVersion string `json:"terraform_version,omitempty"`

	// The values that make up the state.
	Values *StateValues `json:"values,omitempty"`

	// Checks contains the results of any conditional checks when Values was
	// last updated.
	Checks *CheckResultStatic `json:"checks,omitempty"`
}

// UseJSONNumber controls whether the State will be decoded using the
// json.Number behavior or the float64 behavior. When b is true, the State will
// represent numbers in StateOutputs as json.Numbers. When b is false, the
// State will represent numbers in StateOutputs as float64s.
func (s *State) UseJSONNumber(b bool) {
	s.useJSONNumber = b
}

// Validate checks to ensure that the state is present, and the
// version matches the version supported by this library.
func (s *State) Validate() error {
	if s == nil {
		return errors.New("state is nil")
	}

	if s.FormatVersion == "" {
		return errors.New("unexpected state input, format version is missing")
	}

	constraint, err := version.NewConstraint(StateFormatVersionConstraints)
	if err != nil {
		return fmt.Errorf("invalid version constraint: %w", err)
	}

	version, err := version.NewVersion(s.FormatVersion)
	if err != nil {
		return fmt.Errorf("invalid format version %q: %w", s.FormatVersion, err)
	}

	if !constraint.Check(version) {
		return fmt.Errorf("unsupported state format version: %q does not satisfy %q",
			version, constraint)
	}

	return nil
}

func (s *State) UnmarshalJSON(b []byte) error {
	type rawState State
	var state rawState

	dec := json.NewDecoder(bytes.NewReader(b))
	if s.useJSONNumber {
		dec.UseNumber()
	}
	err := dec.Decode(&state)
	if err != nil {
		return err
	}

	*s = *(*State)(&state)

	return s.Validate()
}

// StateValues is the common representation of resolved values for both the
// prior state (which is always complete) and the planned new state.
type StateValues struct {
	// The Outputs for this common state representation.
	Outputs map[string]*StateOutput `json:"outputs,omitempty"`

	// The root module in this state representation.
	RootModule *StateModule `json:"root_module,omitempty"`
}

// StateModule is the representation of a module in the common state
// representation. This can be the root module or a child module.
type StateModule struct {
	// All resources or data sources within this module.
	Resources []*StateResource `json:"resources,omitempty"`

	// The absolute module address, omitted for the root module.
	Address string `json:"address,omitempty"`

	// Any child modules within this module.
	ChildModules []*StateModule `json:"child_modules,omitempty"`
}

// StateResource is the representation of a resource in the common
// state representation.
type StateResource struct {
	// The absolute resource address.
	Address string `json:"address,omitempty"`

	// The resource mode.
	Mode ResourceMode `json:"mode,omitempty"`

	// The resource type, example: "aws_instance" for aws_instance.foo.
	Type string `json:"type,omitempty"`

	// The resource name, example: "foo" for aws_instance.foo.
	Name string `json:"name,omitempty"`

	// The instance key for any resources that have been created using
	// "count" or "for_each". If neither of these apply the key will be
	// empty.
	//
	// This value can be either an integer (int) or a string.
	Index interface{} `json:"index,omitempty"`

	// The name of the provider this resource belongs to. This allows
	// the provider to be interpreted unambiguously in the unusual
	// situation where a provider offers a resource type whose name
	// does not start with its own name, such as the "googlebeta"
	// provider offering "google_compute_instance".
	ProviderName string `json:"provider_name,omitempty"`

	// The version of the resource type schema the "values" property
	// conforms to.
	SchemaVersion uint64 `json:"schema_version,"`

	// The JSON representation of the attribute values of the resource,
	// whose structure depends on the resource type schema. Any unknown
	// values are omitted or set to null, making them indistinguishable
	// from absent values.
	AttributeValues map[string]interface{} `json:"values,omitempty"`

	// The JSON representation of the sensitivity of the resource's
	// attribute values. Only attributes which are sensitive
	// are included in this structure.
	SensitiveValues json.RawMessage `json:"sensitive_values,omitempty"`

	// The addresses of the resources that this resource depends on.
	DependsOn []string `json:"depends_on,omitempty"`

	// If true, the resource has been marked as tainted and will be
	// re-created on the next update.
	Tainted bool `json:"tainted,omitempty"`

	// DeposedKey is set if the resource instance has been marked Deposed and
	// will be destroyed on the next apply.
	DeposedKey string `json:"deposed_key,omitempty"`
}

// StateOutput represents an output value in a common state
// representation.
type StateOutput struct {
	// Whether or not the output was marked as sensitive.
	Sensitive bool `json:"sensitive"`

	// The value of the output.
	Value interface{} `json:"value,omitempty"`

	// The type of the output.
	Type cty.Type `json:"type,omitempty"`
}

// jsonStateOutput describes an output value in a middle-step internal
// representation before marshalled into a more useful StateOutput with cty.Type.
//
// This avoid panic on marshalling cty.NilType (from cty upstream)
// which the default Go marshaller cannot ignore because it's a
// not nil-able struct.
type jsonStateOutput struct {
	Sensitive bool            `json:"sensitive"`
	Value     interface{}     `json:"value,omitempty"`
	Type      json.RawMessage `json:"type,omitempty"`
}

func (so *StateOutput) MarshalJSON() ([]byte, error) {
	jsonSa := &jsonStateOutput{
		Sensitive: so.Sensitive,
		Value:     so.Value,
	}
	if so.Type != cty.NilType {
		outputType, _ := so.Type.MarshalJSON()
		jsonSa.Type = outputType
	}
	return json.Marshal(jsonSa)
}
