package config

import (
	"encoding/json"
	"fmt"
	"os"
	"sync"
	"time"
)

// Config 应用配置
type Config struct {
	Server   ServerConfig  `json:"server"`
	Monitor  MonitorConfig `json:"monitor"`
	DataPath string        `json:"data_path"`
}

// ServerConfig 服务器配置
type ServerConfig struct {
	Port string `json:"port"`
	Host string `json:"host"`
}

// MonitorConfig 监控配置
type MonitorConfig struct {
	Interval    time.Duration `json:"interval"`     // 检测间隔
	Timeout     time.Duration `json:"timeout"`      // 请求超时时间
	RetryCount  int           `json:"retry_count"`  // 重试次数
	HistoryDays int           `json:"history_days"` // 保留历史天数
}

var (
	cfg  *Config
	once sync.Once
)

// GetConfig 获取配置单例
func GetConfig() *Config {
	once.Do(func() {
		cfg = &Config{
			Server: ServerConfig{
				Port: getEnv("SERVER_PORT", "8080"),
				Host: getEnv("SERVER_HOST", "0.0.0.0"),
			},
			Monitor: MonitorConfig{
				Interval:    parseDuration(getEnv("MONITOR_INTERVAL", "1h"), 1*time.Hour),
				Timeout:     parseDuration(getEnv("MONITOR_TIMEOUT", "10s"), 10*time.Second),
				RetryCount:  parseInt(getEnv("MONITOR_RETRY_COUNT", "3"), 3),
				HistoryDays: parseInt(getEnv("MONITOR_HISTORY_DAYS", "90"), 90),
			},
			DataPath: getEnv("DATA_PATH", "./data"),
		}

		// 尝试从配置文件加载（会覆盖环境变量配置）
		loadConfigFromFile()
	})
	return cfg
}

// getEnv 获取环境变量，如果不存在则返回默认值
func getEnv(key, defaultValue string) string {
	if value := os.Getenv(key); value != "" {
		return value
	}
	return defaultValue
}

// parseInt 解析整数环境变量
func parseInt(value string, defaultValue int) int {
	if value == "" {
		return defaultValue
	}
	var result int
	if _, err := fmt.Sscanf(value, "%d", &result); err != nil {
		return defaultValue
	}
	return result
}

// parseDuration 解析时间间隔环境变量
func parseDuration(value string, defaultValue time.Duration) time.Duration {
	if value == "" {
		return defaultValue
	}
	if duration, err := time.ParseDuration(value); err == nil {
		return duration
	}
	return defaultValue
}

// loadConfigFromFile 从文件加载配置
func loadConfigFromFile() {
	configFile := "./data/config.json"
	if _, err := os.Stat(configFile); os.IsNotExist(err) {
		return
	}

	data, err := os.ReadFile(configFile)
	if err != nil {
		return
	}

	var fileCfg struct {
		Server  ServerConfig `json:"server"`
		Monitor struct {
			IntervalMinutes int `json:"interval_minutes"`
			TimeoutSeconds  int `json:"timeout_seconds"`
			RetryCount      int `json:"retry_count"`
			HistoryDays     int `json:"history_days"`
		} `json:"monitor"`
		DataPath string `json:"data_path"`
	}

	if err := json.Unmarshal(data, &fileCfg); err != nil {
		return
	}

	if fileCfg.Server.Port != "" {
		cfg.Server.Port = fileCfg.Server.Port
	}
	if fileCfg.Server.Host != "" {
		cfg.Server.Host = fileCfg.Server.Host
	}
	if fileCfg.Monitor.IntervalMinutes > 0 {
		cfg.Monitor.Interval = time.Duration(fileCfg.Monitor.IntervalMinutes) * time.Minute
	}
	if fileCfg.Monitor.TimeoutSeconds > 0 {
		cfg.Monitor.Timeout = time.Duration(fileCfg.Monitor.TimeoutSeconds) * time.Second
	}
	if fileCfg.Monitor.RetryCount > 0 {
		cfg.Monitor.RetryCount = fileCfg.Monitor.RetryCount
	}
	if fileCfg.Monitor.HistoryDays > 0 {
		cfg.Monitor.HistoryDays = fileCfg.Monitor.HistoryDays
	}
	if fileCfg.DataPath != "" {
		cfg.DataPath = fileCfg.DataPath
	}
}

// SaveConfig 保存配置到文件
func SaveConfig() error {
	configFile := cfg.DataPath + "/config.json"

	fileCfg := struct {
		Server  ServerConfig `json:"server"`
		Monitor struct {
			IntervalMinutes int `json:"interval_minutes"`
			TimeoutSeconds  int `json:"timeout_seconds"`
			RetryCount      int `json:"retry_count"`
			HistoryDays     int `json:"history_days"`
		} `json:"monitor"`
		DataPath string `json:"data_path"`
	}{
		Server: cfg.Server,
		Monitor: struct {
			IntervalMinutes int `json:"interval_minutes"`
			TimeoutSeconds  int `json:"timeout_seconds"`
			RetryCount      int `json:"retry_count"`
			HistoryDays     int `json:"history_days"`
		}{
			IntervalMinutes: int(cfg.Monitor.Interval.Minutes()),
			TimeoutSeconds:  int(cfg.Monitor.Timeout.Seconds()),
			RetryCount:      cfg.Monitor.RetryCount,
			HistoryDays:     cfg.Monitor.HistoryDays,
		},
		DataPath: cfg.DataPath,
	}

	data, err := json.MarshalIndent(fileCfg, "", "  ")
	if err != nil {
		return err
	}

	return os.WriteFile(configFile, data, 0644)
}
