package internal

import (
	"os"
	"slices"
	"strconv"
	"strings"

	"github.com/juju/errors"
	log "github.com/sirupsen/logrus"
	"github.com/tidbcloud/auto-deploy/internal/constants"
	global_client "github.com/tidbcloud/auto-deploy/internal/global-client"
	"github.com/tidbcloud/auto-deploy/internal/types"
)

type UpdateRegionInfoArgs struct {
	Env             string
	CloudProvider   string
	LogicalName     string
	State           string
	IsPublic        string
	DeployType      string
	OpenedTenantIds []string
}

func UpdateRegion(args UpdateRegionInfoArgs) error {
	authKey := os.Getenv(constants.GLOBAL_AUTH_KEY_ENV)
	cloudProvider := types.CloudProviderType(args.CloudProvider)
	if !slices.Contains(types.CloudProviderTypes, cloudProvider) {
		return errors.NotSupportedf("cloud provider %s", args.CloudProvider)
	}

	var public *bool = nil
	if args.IsPublic != "" {
		val, err := strconv.ParseBool(args.IsPublic)
		if err != nil {
			return errors.NotValidf("is-public %s", args.IsPublic)
		}
		public = &val
	}

	state := strings.ToUpper(args.State)
	if state != "" && state != global_client.INACTIVE_STATE && state != global_client.ACTIVE_STATE {
		return errors.NotValidf("state %s", args.State)
	}

	// we need to distinguish "not set" and "empty list"
	// we use an invalid tenant id "cleared" to indicate that we need to clear all tenants.
	// empty list is "not set", so we keep the old values
	if len(args.OpenedTenantIds) == 1 && args.OpenedTenantIds[0] == "cleared" {
		args.OpenedTenantIds = make([]string, 0)
	} else if len(args.OpenedTenantIds) == 0 {
		args.OpenedTenantIds = nil
	} else {
		for _, id := range args.OpenedTenantIds {
			_, err := strconv.ParseInt(id, 10, 64)
			if err != nil {
				return errors.NotValidf("invalid tenant id %s", id)
			}
		}
	}

	log.WithFields(log.Fields{
		"cloud":           args.CloudProvider,
		"region":          args.LogicalName,
		"state":           args.State,
		"is-public":       args.IsPublic,
		"deploy-type":     args.DeployType,
		"open-tenant-ids": args.OpenedTenantIds,
	}).Info("Update region")
	client := global_client.NewGlobalClient(args.Env, authKey, global_client.DEFAULT_TIMEOUT, log.IsLevelEnabled(log.DebugLevel))
	return client.UpdateRegionInfo(args.DeployType, cloudProvider, args.LogicalName, state, public, args.OpenedTenantIds)
}
