package types

import (
	"fmt"
	"strings"

	"github.com/juju/errors"
	"gopkg.in/yaml.v3"
)

type Instance struct {
	Regions map[string]Region `yaml:"regions"`
}

type Region struct {
	CloudProvider        CloudProvider        `yaml:"-"` // from CloudProviderType
	OidcProvider         OidcProvider         `yaml:"-"` // runtime property
	InstanceName         string               `yaml:"-"` // runtime property
	Name                 string               `yaml:"-"` // map key
	Account              Account              `yaml:"account"`
	CloudProviderType    CloudProviderType    `yaml:"cloud-provider"`
	Region               string               `yaml:"region"`
	K8s                  K8s                  `yaml:"k8s"`
	LatestRunId          string               `yaml:"latest-run-id"`
	OutputBucket         string               `yaml:"output-bucket"`
	TerraformStateBucket string               `yaml:"tf-state-bucket,omitempty"`
	JobPath              string               `yaml:"job-path"`
	JobOutputs           map[string]JobOutput `yaml:"job-outputs"`
	TidbClusterAccounts  []Account            `yaml:"tidb-cluster-accounts,omitempty"`
	ImageRegistry        string               `yaml:"image-registry,omitempty"`
	JobOptions           map[string]any       `yaml:"job-options"`
	GlobalOptions        GlobalOptions        `yaml:"global-options,omitempty"`
}

func (region Region) Print() {
	bytes, err := yaml.Marshal(&region)
	if err != nil {
		fmt.Println("Failed to marshal region:", err.Error())
	}
	fmt.Println(string(bytes))
}

func (r *Region) GetJobOption(path string) (any, error) {
	keys := strings.Split(path, ".")
	m := r.JobOptions
	lastIndex := len(keys) - 1
	for i, key := range keys {
		v, ok := m[key]
		if !ok {
			return nil, errors.NotFoundf("%s not found in job options", path)
		}
		if i == lastIndex {
			return v, nil
		}
		m, ok = v.(map[string]any)
		if !ok {
			return nil, errors.NotValidf("%s is invalid for job options", path)
		}
	}
	return nil, nil
}

type K8s struct {
	CredentialSecretName string         `yaml:"-"` // don't save
	CredentialSecret     string         `yaml:"-"` // don't save
	Region               *Region        `yaml:"-"` // don't save
	Name                 string         `yaml:"name"`
	Version              string         `yaml:"version"`
	OidcIssuer           string         `yaml:"oidc-issuer"`
	EndPoint             string         `yaml:"endpoint"`
	PublicIps            []string       `yaml:"public-ips"`
	Options              map[string]any `yaml:",inline"`
}

type GlobalOptions struct {
	OpenedTenantIds   []string `yaml:"openedTenantIds"`
	SortPriority      int      `yaml:"sortPriority"`
	Public            bool     `yaml:"isPublic"`
	Env               string   `yaml:"env,omitempty"`
	LogicalRegionName string   `yaml:"logicalName,omitempty"`
}

type TidbClusterAccount struct {
	Profile string `yaml:"aws-profile,omitempty"`
}

type JobOutput struct {
	Version string `yaml:"version"`
	Output  string `yaml:"output"`
}
