package db

import (
	"fmt"
	"os"
	"path/filepath"
	"strings"
	"sync"

	"GoNavi-Wails/internal/appdata"
)

// coreBuiltinDrivers 是始终内置可用的核心驱动，无需额外安装即可使用。
var coreBuiltinDrivers = map[string]struct{}{
	"mysql":    {},
	"redis":    {},
	"oracle":   {},
	"postgres": {},
}

// optionalGoDrivers 表示需要用户“安装启用”后才能使用的纯 Go 驱动。
// 注意：这是一种运行时门控（installed.json 标记），并不减少主二进制体积。
var optionalGoDrivers = map[string]struct{}{
	"mariadb":    {},
	"oceanbase":  {},
	"diros":      {},
	"starrocks":  {},
	"sphinx":     {},
	"sqlserver":  {},
	"sqlite":     {},
	"duckdb":     {},
	"dameng":     {},
	"kingbase":   {},
	"highgo":     {},
	"vastbase":   {},
	"opengauss":  {},
	"iris":       {},
	"mongodb":      {},
	"tdengine":     {},
	"clickhouse":   {},
	"elasticsearch": {},
}

// optionalDriverAgentRevisions 记录 GoNavi 对各可选 driver-agent 包装逻辑的兼容版本。
// 该 map 由 tools/generate-driver-agent-revisions.sh 按 driver-agent 源码依赖自动生成，
// 避免人工判断需要 bump 哪个驱动 revision。
var optionalDriverAgentRevisions = map[string]string{}

var (
	externalDriverDirMu sync.RWMutex
	externalDriverDir   string
)

func normalizeRuntimeDriverType(driverType string) string {
	normalized := strings.ToLower(strings.TrimSpace(driverType))
	switch normalized {
	case "doris":
		return "diros"
	case "postgresql":
		return "postgres"
	case "kingbase8", "kingbasees", "kingbasev8":
		return "kingbase"
	case "opengauss", "open_gauss", "open-gauss":
		return "opengauss"
	case "intersystems", "intersystemsiris", "inter-systems-iris", "inter-systems":
		return "iris"
	case "elastic":
		return "elasticsearch"
	default:
		return normalized
	}
}

func driverDisplayName(driverType string) string {
	switch normalizeRuntimeDriverType(driverType) {
	case "mysql":
		return "MySQL"
	case "oracle":
		return "Oracle"
	case "redis":
		return "Redis"
	case "mariadb":
		return "MariaDB"
	case "oceanbase":
		return "OceanBase"
	case "diros":
		return "Doris"
	case "starrocks":
		return "StarRocks"
	case "sphinx":
		return "Sphinx"
	case "postgres":
		return "PostgreSQL"
	case "sqlserver":
		return "SQL Server"
	case "sqlite":
		return "SQLite"
	case "duckdb":
		return "DuckDB"
	case "dameng":
		return "Dameng"
	case "kingbase":
		return "Kingbase"
	case "highgo":
		return "HighGo"
	case "vastbase":
		return "Vastbase"
	case "opengauss":
		return "OpenGauss"
	case "iris":
		return "InterSystems IRIS"
	case "mongodb":
		return "MongoDB"
	case "tdengine":
		return "TDengine"
	case "clickhouse":
		return "ClickHouse"
	case "elasticsearch":
		return "Elasticsearch"
	default:
		return strings.ToUpper(strings.TrimSpace(driverType))
	}
}

// IsOptionalGoDriver 返回指定驱动类型是否为可选的纯 Go 驱动。
// 可选驱动需要用户在驱动管理界面点击“安装启用”后才能使用。
func IsOptionalGoDriver(driverType string) bool {
	_, ok := optionalGoDrivers[normalizeRuntimeDriverType(driverType)]
	return ok
}

func IsOptionalGoDriverBuildIncluded(driverType string) bool {
	return optionalGoDriverBuildIncluded(normalizeRuntimeDriverType(driverType))
}

func OptionalDriverAgentRevision(driverType string) string {
	return strings.TrimSpace(optionalDriverAgentRevisions[normalizeRuntimeDriverType(driverType)])
}

// IsBuiltinDriver 返回指定驱动类型是否为核心内置驱动（始终可用，无需安装）。
func IsBuiltinDriver(driverType string) bool {
	_, ok := coreBuiltinDrivers[normalizeRuntimeDriverType(driverType)]
	return ok
}

func defaultExternalDriverDownloadDirectory() string {
	return appdata.DriverRoot("")
}

func resolveExternalDriverRoot(downloadDir string) (string, error) {
	root := strings.TrimSpace(downloadDir)
	if root == "" {
		root = currentExternalDriverDownloadDirectory()
	}
	if root == "" {
		root = defaultExternalDriverDownloadDirectory()
	}
	if !filepath.IsAbs(root) {
		abs, err := filepath.Abs(root)
		if err != nil {
			return "", err
		}
		root = abs
	}
	if err := os.MkdirAll(root, 0o755); err != nil {
		return "", fmt.Errorf("创建驱动目录失败：%w", err)
	}
	return root, nil
}

func currentExternalDriverDownloadDirectory() string {
	externalDriverDirMu.RLock()
	current := strings.TrimSpace(externalDriverDir)
	externalDriverDirMu.RUnlock()
	if current != "" {
		return current
	}
	return defaultExternalDriverDownloadDirectory()
}

// SetExternalDriverDownloadDirectory 设置可选驱动的下载存储目录。
// 如果路径解析失败，会回退到默认目录（~/.gonavi/drivers）。
func SetExternalDriverDownloadDirectory(downloadDir string) {
	root, err := resolveExternalDriverRoot(downloadDir)
	if err != nil {
		root = defaultExternalDriverDownloadDirectory()
	}
	externalDriverDirMu.Lock()
	externalDriverDir = root
	externalDriverDirMu.Unlock()
}

func ResolveExternalDriverRoot(downloadDir string) (string, error) {
	return resolveExternalDriverRoot(downloadDir)
}

func ResolveOptionalGoDriverMarkerPath(downloadDir string, driverType string) (string, error) {
	normalized := normalizeRuntimeDriverType(driverType)
	if !IsOptionalGoDriver(normalized) {
		return "", fmt.Errorf("%s 不是可选 Go 驱动", driverDisplayName(normalized))
	}
	root, err := resolveExternalDriverRoot(downloadDir)
	if err != nil {
		return "", err
	}
	return filepath.Join(root, normalized, "installed.json"), nil
}

func optionalGoDriverInstalled(driverType string) bool {
	markerPath, err := ResolveOptionalGoDriverMarkerPath("", driverType)
	if err != nil {
		return false
	}
	info, statErr := os.Stat(markerPath)
	return statErr == nil && !info.IsDir()
}

func optionalGoDriverRuntimeReady(driverType string) (bool, string) {
	normalized := normalizeRuntimeDriverType(driverType)
	if !IsOptionalGoDriver(normalized) {
		return true, ""
	}
	executablePath, err := ResolveOptionalDriverAgentExecutablePath("", normalized)
	if err != nil {
		return false, fmt.Sprintf("%s 驱动代理路径解析失败，请在驱动管理中重新安装启用", driverDisplayName(normalized))
	}
	info, statErr := os.Stat(executablePath)
	if statErr != nil || info.IsDir() {
		return false, fmt.Sprintf("%s 驱动代理缺失，请在驱动管理中重新安装启用", driverDisplayName(normalized))
	}
	if validateErr := ValidateOptionalDriverAgentExecutable(normalized, executablePath); validateErr != nil {
		return false, fmt.Sprintf("%s；请在驱动管理中重新安装启用", validateErr.Error())
	}
	return true, ""
}

// DriverRuntimeSupportStatus 返回当前构建下驱动是否可用（可直接用于连接）。
func DriverRuntimeSupportStatus(driverType string) (bool, string) {
	normalized := normalizeRuntimeDriverType(driverType)
	if normalized == "" {
		return false, "未识别的数据源类型"
	}
	if normalized == "custom" {
		return true, ""
	}
	if IsBuiltinDriver(normalized) {
		return true, ""
	}
	if IsOptionalGoDriver(normalized) {
		if !IsOptionalGoDriverBuildIncluded(normalized) {
			return false, fmt.Sprintf("%s 当前发行包为精简构建，未内置该驱动；如需使用请安装 Full 版", driverDisplayName(normalized))
		}
		if optionalGoDriverInstalled(normalized) {
			if ready, reason := optionalGoDriverRuntimeReady(normalized); !ready {
				return false, reason
			}
			return true, ""
		}
		return false, fmt.Sprintf("%s 纯 Go 驱动未启用，请先在驱动管理中点击“安装启用”", driverDisplayName(normalized))
	}
	return true, ""
}
