package engine_router

import (
	"context"
	"fmt"
	"strings"

	"github.com/pingcap-inc/clinic/clinic_data_service/pkg/dto"
	"github.com/pingcap-inc/clinic/clinic_data_service/pkg/log"
	"go.uber.org/zap"
)

// ValidAWSRegions AWS 所有有效的 region 列表
var ValidAWSRegions = []string{
	// 美国区域
	"us-east-1", "us-east-2", "us-west-1", "us-west-2",
	// 亚太区域
	"ap-northeast-1", "ap-northeast-2", "ap-northeast-3",
	"ap-southeast-1", "ap-southeast-2", "ap-southeast-3", "ap-southeast-4", "ap-southeast-5", "ap-southeast-7",
	"ap-south-1", "ap-south-2", "ap-east-1",
	// 欧洲区域
	"eu-west-1", "eu-west-2", "eu-west-3",
	"eu-central-1", "eu-central-2",
	"eu-north-1", "eu-south-1", "eu-south-2",
	// 加拿大区域
	"ca-central-1", "ca-west-1",
	// 南美区域
	"sa-east-1",
	// 中东区域
	"me-south-1", "me-central-1",
	// 非洲区域
	"af-south-1",
}

// ValidateAWSRegion 验证 AWS region 是否有效
func ValidateAWSRegion(region string) error {
	if region == "" {
		return nil // 空 region 允许，会自动检测
	}

	for _, validRegion := range ValidAWSRegions {
		if region == validRegion {
			return nil
		}
	}

	return fmt.Errorf("invalid AWS region '%s'. Valid regions are: %s",
		region, strings.Join(ValidAWSRegions, ", "))
}

// DetectAWSRegion 从 S3 Bucket 名称推断 AWS Region
// 策略：
// 1. 从 bucket 命名规则推断（如 bucket-us-east-1）
// 2. 从配置文件读取映射关系
// 3. 使用默认 Region
func DetectAWSRegion(ctx context.Context, bucket string) (string, error) {
	bucketLower := strings.ToLower(bucket)

	// 尝试从 bucket 名称中匹配 region
	for _, region := range ValidAWSRegions {
		if strings.Contains(bucketLower, region) {
			log.Info(ctx, "Successfully detected AWS region from bucket", zap.String("region", region))
			return region, nil
		}
	}

	err := fmt.Errorf("failed to detect AWS region from bucket name: %s", bucket)
	log.Error(ctx, "DetectAWSRegion failed")
	return "", err
}

// DetectGCPRegion 从 GCS Bucket 名称推断 GCP Region
func DetectGCPRegion(bucket string) string {
	// GCP Region 示例：
	// us-central1, us-east1, us-west1
	// asia-northeast1, asia-southeast1
	// europe-west1, europe-west2

	regions := []string{
		"us-central1", "us-east1", "us-west1",
		"asia-northeast1", "asia-southeast1", "asia-east1",
		"europe-west1", "europe-west2",
	}

	bucketLower := strings.ToLower(bucket)

	for _, region := range regions {
		if strings.Contains(bucketLower, region) {
			return region
		}
	}

	// 默认返回 us-central1
	return "us-central1"
}

// DetectAliyunRegion 从 OSS Bucket 名称推断阿里云 Region
func DetectAliyunRegion(bucket string) string {
	// 阿里云 Region 示例：
	// cn-hangzhou, cn-shanghai, cn-beijing
	// ap-southeast-1 (新加坡)

	regions := []string{
		"cn-hangzhou", "cn-shanghai", "cn-beijing", "cn-shenzhen",
		"ap-southeast-1", "ap-southeast-2", "ap-southeast-3",
		"us-east-1", "us-west-1",
	}

	bucketLower := strings.ToLower(bucket)

	for _, region := range regions {
		if strings.Contains(bucketLower, region) {
			return region
		}
	}

	// 默认返回 ap-southeast-1（新加坡）
	return "ap-southeast-1"
}

// DetectAzureRegion 从 Azure account/container/path 中尽力推断 region。
// Azure storage URL 本身不强制携带 region，无法推断时返回空字符串，由请求 options.region 或配置补齐。
func DetectAzureRegion(info *dto.DataSourceInfo) string {
	regions := []string{
		"eastus", "eastus2", "westus", "westus2", "westus3",
		"centralus", "northcentralus", "southcentralus", "westcentralus",
		"canadacentral", "canadaeast",
		"brazilsouth",
		"northeurope", "westeurope", "uksouth", "ukwest",
		"francecentral", "germanywestcentral", "switzerlandnorth",
		"norwayeast", "swedencentral",
		"eastasia", "southeastasia", "japaneast", "japanwest",
		"koreacentral", "koreasouth", "australiaeast", "australiasoutheast",
		"centralindia", "southindia", "westindia",
		"uaenorth", "qatarcentral", "israelcentral",
	}

	source := strings.ToLower(strings.Join([]string{
		info.Account,
		info.Container,
		info.Bucket,
		info.Path,
		info.FullURI,
	}, " "))
	for _, region := range regions {
		if strings.Contains(source, region) {
			return region
		}
	}
	return ""
}

// ParseAndDetectDataSource 解析数据源并自动检测 Region
func ParseAndDetectDataSource(ctx context.Context, uri string) (*dto.DataSourceInfo, error) {
	info, err := dto.ParseDataSource(uri)
	if err != nil {
		return nil, err
	}

	// 根据云厂商检测 Region
	switch info.Vendor {
	case "aws":
		region, err := DetectAWSRegion(ctx, info.Bucket)
		if err != nil {
			log.Error(ctx, "ParseAndDetectDataSource failed to detect AWS region")
			return nil, err
		}
		info.Region = region
	case "gcp":
		info.Region = DetectGCPRegion(info.Bucket)
	case "alicloud":
		info.Region = DetectAliyunRegion(info.Bucket)
	case "azure":
		info.Region = DetectAzureRegion(info)
	default:
		return nil, fmt.Errorf("unsupported vendor: %s", info.Vendor)
	}

	return info, nil
}
