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

package genconfig

import (
	"fmt"
	"io"
	"os"

	"github.com/opentofu/opentofu/internal/tfdiags"
)

func ShouldWriteConfig(out string) bool {
	// No specified out file, so don't write anything.
	return len(out) != 0
}

func ValidateTargetFile(out string) (diags tfdiags.Diagnostics) {
	if _, err := os.Stat(out); !os.IsNotExist(err) {
		diags = diags.Append(tfdiags.Sourceless(
			tfdiags.Error,
			"Target generated file already exists",
			"OpenTofu can only write generated config into a new file. Either choose a different target location or move all existing configuration out of the target file, delete it and try again."))

	}
	return diags
}

type Change struct {
	Addr            string
	ImportID        string
	GeneratedConfig string
}

func (c *Change) MaybeWriteConfig(writer io.Writer, out string) (io.Writer, bool, tfdiags.Diagnostics) {
	var wroteConfig bool
	var diags tfdiags.Diagnostics
	if len(c.GeneratedConfig) > 0 {
		if writer == nil {
			// Lazily create the generated file, in case we have no
			// generated config to create.
			if w, err := os.Create(out); err != nil {
				if os.IsPermission(err) {
					diags = diags.Append(tfdiags.Sourceless(
						tfdiags.Error,
						"Failed to create target generated file",
						fmt.Sprintf("OpenTofu did not have permission to create the generated file (%s) in the target directory. Please modify permissions over the target directory, and try again.", out)))
					return nil, false, diags
				}

				diags = diags.Append(tfdiags.Sourceless(
					tfdiags.Error,
					"Failed to create target generated file",
					fmt.Sprintf("OpenTofu could not create the generated file (%s) in the target directory: %v. Depending on the error message, this may be a bug in OpenTofu itself. If so, please report it!", out, err)))
				return nil, false, diags
			} else {
				writer = w
			}

			header := "# __generated__ by OpenTofu\n# Please review these resources and move them into your main configuration files.\n"
			// Missing the header from the file, isn't the end of the world
			// so if this did return an error, then we will just ignore it.
			_, _ = writer.Write([]byte(header))
		}

		header := "\n# __generated__ by OpenTofu"
		if len(c.ImportID) > 0 {
			header += fmt.Sprintf(" from %q", c.ImportID)
		}
		header += "\n"
		if _, err := fmt.Fprintf(writer, "%s%s\n", header, c.GeneratedConfig); err != nil {
			diags = diags.Append(tfdiags.Sourceless(
				tfdiags.Warning,
				"Failed to save generated config",
				fmt.Sprintf("OpenTofu encountered an error while writing generated config: %v. The config for %s must be created manually before applying. Depending on the error message, this may be a bug in OpenTofu itself. If so, please report it!", err, c.Addr)))
		}
		wroteConfig = true
	}

	return writer, wroteConfig, diags
}
