package common

import (
	"errors"
	"fmt"
	"regexp"
	"strconv"
	"strings"

	openapicommonv1beta1 "github.com/tidbcloud/tidb-management-service/api/spec/tidb_cloud_open_api/common/v1beta1"
	"github.com/tidbcloud/tidb-management-service/utilities/enum"
)

var (
	genericNameRegexp     = regexp.MustCompile(`^[A-Za-z0-9][-A-Za-z0-9]{2,62}[A-Za-z0-9]$`)
	RegionStrRegexp       = regexp.MustCompile(`(aws|gcp|azure|alicloud)-(.+)`)
	vpcPeeringIdStrRegexp = regexp.MustCompile(`(aws|gcp|azure)-(.+)`)
)

func ParseOpenApiRegionNameOrId(regionNameOrId string) (provider, region string, err error) {
	regionId := strings.TrimPrefix(regionNameOrId, "regions/")

	if regionId == "" {
		return "", "", errors.New("region is not set")
	}
	m := RegionStrRegexp.FindStringSubmatch(regionId)
	if len(m) != 3 {
		return "", "", errors.New("invalid provider and region string")
	}
	return strings.ToLower(m[1]), strings.ToLower(m[2]), err
}

func BuildOpenApiRegionName(
	provider, regionCode string,
) (name, id string, cloudProvider openapicommonv1beta1.Region_CloudProvider, err error) {
	if regionCode == "" {
		return "", "", 0, nil
	}
	p, err := enum.FromString[openapicommonv1beta1.Region_CloudProvider](provider)
	if err != nil {
		return "", "", 0, err
	}
	cloudProvider = openapicommonv1beta1.Region_CloudProvider(p)
	name = fmt.Sprintf("regions/%s-%s", cloudProvider, regionCode)
	id = fmt.Sprintf("%s-%s", cloudProvider, regionCode)
	return name, id, cloudProvider, nil
}

func CheckDisplayNameFmt(name string) bool {
	return genericNameRegexp.MatchString(name)
}

func ParseVpcPeeringOpenApiId(openApiId string) (openapicommonv1beta1.Region_CloudProvider, uint64, error) {
	idStr := strings.TrimPrefix(openApiId, "vpcPeerings/")
	m := vpcPeeringIdStrRegexp.FindStringSubmatch(idStr)
	if len(m) != 3 {
		return openapicommonv1beta1.Region_CLOUD_PROVIDER_UNSPECIFIED, 0, errors.New(
			"invalid provider and region string",
		)
	}
	p, err := enum.FromString[openapicommonv1beta1.Region_CloudProvider](m[1])
	if err != nil {
		return openapicommonv1beta1.Region_CLOUD_PROVIDER_UNSPECIFIED, 0, err
	}
	id, err := strconv.ParseUint(m[2], 10, 64)
	if err != nil {
		return openapicommonv1beta1.Region_CLOUD_PROVIDER_UNSPECIFIED, 0, err
	}
	return openapicommonv1beta1.Region_CloudProvider(p), id, err
}
