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

package oci

import (
	"fmt"
	"os"
	"path"
	"regexp"
	"strings"
	"time"

	"github.com/hashicorp/terraform/internal/backend/backendbase"
	"github.com/hashicorp/terraform/internal/tfdiags"
	"github.com/zclconf/go-cty/cty"
)

func getEnvSettingWithBlankDefault(s string) string {
	return getEnvSettingWithDefault(s, "")
}

func getEnvSettingWithDefault(s string, dv string) string {
	v := os.Getenv(OciEnvPrefix + s)
	if v != "" {
		return v
	}
	v = os.Getenv(s)
	if v != "" {
		return v
	}
	return dv
}
func getDurationFromEnvVar(varName string, defaultValue time.Duration) time.Duration {
	valueStr := getEnvSettingWithDefault(varName, fmt.Sprint(defaultValue))
	duration, err := time.ParseDuration(valueStr)
	if err != nil {
		loggerFunc().Error("ERROR while parsing env variable %s value: %v", varName, err)
		return defaultValue
	}
	return duration
}
func getHomeFolder() string {
	if os.Getenv("OCI_HOME_OVERRIDE") != "" {
		return os.Getenv("OCI_HOME_OVERRIDE")
	}
	home, err := os.UserHomeDir()
	if err != nil {
		loggerFunc().Error("ERROR while getting home directory: %v", err)
		return ""
	}
	return home
}
func checkProfile(profile string, path string) (err error) {
	var profileRegex = regexp.MustCompile(`^\[(.*)\]`)
	data, err := os.ReadFile(path)
	if err != nil {
		return err
	}
	content := string(data)
	splitContent := strings.Split(content, "\n")
	for _, line := range splitContent {
		if match := profileRegex.FindStringSubmatch(line); match != nil && len(match) > 1 && match[1] == profile {
			return nil
		}
	}

	return fmt.Errorf("configuration file did not contain profile: %s", profile)
}

// cleans and expands the path if it contains a tilde , returns the expanded path or the input path as is if not expansion
// was performed
func expandPath(filepath string) string {
	if strings.HasPrefix(filepath, fmt.Sprintf("~%c", os.PathSeparator)) {
		filepath = path.Join(getHomeFolder(), filepath[2:])
	}
	return path.Clean(filepath)
}

func getBackendAttrWithDefault(obj cty.Value, attrName, def string) (cty.Value, bool) {
	value := backendbase.GetAttrDefault(obj, attrName, cty.StringVal(getEnvSettingWithDefault(attrName, def)))
	return value, value.IsKnown() && !value.IsNull()
}

func getBackendAttr(obj cty.Value, attrName string) (cty.Value, bool) {
	return getBackendAttrWithDefault(obj, attrName, "")
}
func uniqueStrings(input []string) []string {
	seen := make(map[string]bool)
	var result []string

	for _, val := range input {
		if !seen[val] {
			seen[val] = true
			result = append(result, val)
		}
	}
	return result
}

func validateStringObjectPath(val string, path cty.Path, diags *tfdiags.Diagnostics) {
	if strings.HasPrefix(val, "/") || strings.HasSuffix(val, "/") || strings.Contains(val, "//") {
		*diags = diags.Append(tfdiags.AttributeValue(tfdiags.Error,
			"Invalid Value",
			`The value must not start or end with "/" and also not contain consecutive "/"`,
			path.Copy(),
		))
	}
}

func validateStringWorkspacePrefix(val string, path cty.Path, diags *tfdiags.Diagnostics) {
	if strings.HasPrefix(val, "/") || strings.Contains(val, "//") {
		*diags = diags.Append(tfdiags.AttributeValue(tfdiags.Error,
			"Invalid Value",
			`The value must not start  with "/" and also not contain consecutive "/"`,
			path.Copy(),
		))
	}
}

func validateStringBucketName(val string, path cty.Path, diags *tfdiags.Diagnostics) {
	match, _ := regexp.MatchString(`^[a-zA-Z0-9_-]+$`, val)
	if !match {
		*diags = diags.Append(tfdiags.AttributeValue(tfdiags.Error,
			"Invalid Value",
			`The bucket name can only include alphanumeric characters, underscores (_), and hyphens (-).`,
			path.Copy(),
		))
	}
}
func requiredAttributeErrDiag(path cty.Path) tfdiags.Diagnostic {
	return tfdiags.AttributeValue(tfdiags.Error,
		"Missing Required Value",
		fmt.Sprintf("The attribute %q is required by the backend.\n\n", path)+
			"Refer to the backend documentation for additional information which attributes are required.",
		path,
	)
}
func attributeErrDiag(summary, detail string, path cty.Path) tfdiags.Diagnostic {
	return tfdiags.AttributeValue(
		tfdiags.Error,
		summary,
		detail,
		path,
	)
}

func attributeWarningDiag(summary, detail string, path cty.Path) tfdiags.Diagnostic {
	return tfdiags.AttributeValue(
		tfdiags.Warning,
		summary,
		detail,
		path,
	)
}
