package service

import (
	"fmt"
	"regexp"
	"strings"

	v1 "k8s.io/api/core/v1"
)

const tikvGracePeriodSeconds = 30

const alicloudECSInstanceIDLabelKey = "alibabacloud.com/ecs-instance-id"

var (
	gcpProviderIDPattern = regexp.MustCompile(`^gce://([^/]+)/([^/]+)/([^/]+)$`)
)

func getCloudProviderFromNode(node *v1.Node) (string, error) {
	if node.Labels[alicloudECSInstanceIDLabelKey] != "" {
		return "alicloud", nil
	}

	providerID := node.Spec.ProviderID
	if providerID == "" {
		return "", fmt.Errorf("providerID is empty")
	}
	if parts := strings.Split(providerID, "://"); len(parts) != 2 {
		return "", fmt.Errorf("providerID format is incorrect")
	} else {
		if parts[0] == "gce" {
			return "gcp", nil
		}
		return parts[0], nil
	}
}

// parseEKSNodeProviderID extracts EC2 instance id from the `spec.providerID` of a EKS node.
// The `providerID` looks like `aws:///us-west-2a/i-xxxxx`.
func parseEKSNodeProviderID(providerID string) (region, instanceID string, err error) {
	parts := strings.Split(providerID, "/")

	if len(parts) == 5 {
		// Extract region (removing the last character to get rid of the availability zone)
		region = parts[3][:len(parts[3])-1]

		instanceID = parts[4]
		return region, instanceID, nil
	}

	return "", "", fmt.Errorf("invalid EKS node providerID: %s", providerID)
}

// parseGKENodeProviderID extracts GCP project id, zone and instance name from the `spec.providerID` of a GKE node.
// The `providerID` looks like `gce://<project-id>/<zone>/gke-xxx-node-po-xxx`.
func parseGKENodeProviderID(providerID string) (projectID, zone, instanceName string, err error) {
	matches := gcpProviderIDPattern.FindStringSubmatch(providerID)

	if len(matches) < 4 {
		return "", "", "", fmt.Errorf("invalid GKE node providerID: %s", providerID)
	}

	return matches[1], matches[2], matches[3], nil
}

// azure:///subscriptions/<subscription>/resourceGroups/<resource-group>/providers/Microsoft.Compute/virtualMachineScaleSets/<vmss>/virtualMachines/<instance-id>
func parseAKSNodeProviderID(providerID string) (subscription, resourceGroup, vmss, instanceID string, err error) {
	s := strings.TrimPrefix(providerID, "azure:///")
	parts := strings.Split(s, "/")
	if len(parts) != 10 {
		return "", "", "", "", fmt.Errorf("invalid AKS node providerID: %s", providerID)
	}
	return parts[1], parts[3], parts[7], parts[9], nil
}

// providerID format: kind://docker/kind/kind-control-plane
//
//nolint:unused // Reserved for future Kind support
func parseKindNodeProviderID(providerID string) (string, error) {
	s := strings.Split(providerID, "/")
	if len(s) == 5 {
		return s[len(s)-1], nil
	}
	return "", fmt.Errorf("invalid kind node providerID: %s", providerID)
}

func parseAlicloudNodeProviderID(providerID string) (region, instanceID string, err error) {
	parts := strings.SplitN(providerID, ".i-", 2)
	if len(parts) != 2 || parts[0] == "" || parts[1] == "" {
		return "", "", fmt.Errorf("invalid Alicloud providerID format: %s", providerID)
	}

	return parts[0], "i-" + parts[1], nil
}

func parseAlicloudInstanceIDFromNode(node *v1.Node) (string, error) {
	if instanceID := node.Labels[alicloudECSInstanceIDLabelKey]; instanceID != "" {
		return instanceID, nil
	}

	_, instanceID, err := parseAlicloudNodeProviderID(node.Spec.ProviderID)
	return instanceID, err
}
