package config

import (
	"os"
	"strconv"
	"strings"
	"time"
)

type Config struct {
	HTTPAddr                string
	StaticDir               string
	MySQLDSN                string
	RedisAddr               string
	RedisUsername           string
	RedisPassword           string
	RedisDB                 int
	TDengineDriver          string
	TDengineDSN             string
	TDengineDatabase        string
	CapacityCheckBin        string
	AuthToken               string
	AuthMode                string
	AuthTokensJSON          string
	BootstrapAdminUsername  string
	BootstrapAdminPassword  string
	SessionTTL              time.Duration
	DataMode                string
	ExportDir               string
	RequestTimeout          time.Duration
	AMapWebJSKey            string
	AMapAPIKey              string
	AMapSecurityCode        string
	AMapServiceHost         string
	PlatformRelease         string
	AlertEvaluationInterval time.Duration
	AlertStreamMode         string
	AlertStreamKafkaBrokers []string
	AlertStreamKafkaTopics  []string
	AlertStreamKafkaGroup   string
	AlertStreamBatchSize    int
	AlertStreamBatchWait    time.Duration
	AlertStreamLateness     time.Duration
}

func Load() Config {
	return Config{
		HTTPAddr:                env("HTTP_ADDR", ":20300"),
		StaticDir:               env("STATIC_DIR", ""),
		MySQLDSN:                os.Getenv("MYSQL_DSN"),
		RedisAddr:               os.Getenv("REDIS_ADDR"),
		RedisUsername:           os.Getenv("REDIS_USERNAME"),
		RedisPassword:           os.Getenv("REDIS_PASSWORD"),
		RedisDB:                 envInt("REDIS_DB", 50),
		TDengineDriver:          env("TDENGINE_DRIVER", "taosWS"),
		TDengineDSN:             os.Getenv("TDENGINE_DSN"),
		TDengineDatabase:        env("TDENGINE_DATABASE", "lingniu_vehicle_ts"),
		CapacityCheckBin:        os.Getenv("CAPACITY_CHECK_BIN"),
		AuthToken:               os.Getenv("AUTH_TOKEN"),
		AuthMode:                authMode(),
		AuthTokensJSON:          os.Getenv("AUTH_TOKENS_JSON"),
		BootstrapAdminUsername:  os.Getenv("BOOTSTRAP_ADMIN_USERNAME"),
		BootstrapAdminPassword:  os.Getenv("BOOTSTRAP_ADMIN_PASSWORD"),
		SessionTTL:              time.Duration(envInt("AUTH_SESSION_TTL_HOURS", 12)) * time.Hour,
		DataMode:                dataMode(),
		ExportDir:               os.Getenv("EXPORT_DIR"),
		RequestTimeout:          time.Duration(envInt("REQUEST_TIMEOUT_MS", 5000)) * time.Millisecond,
		AMapWebJSKey:            os.Getenv("AMAP_WEB_JS_KEY"),
		AMapAPIKey:              os.Getenv("AMAP_API_KEY"),
		AMapSecurityCode:        os.Getenv("AMAP_SECURITY_JS_CODE"),
		AMapServiceHost:         os.Getenv("AMAP_SECURITY_SERVICE_HOST"),
		PlatformRelease:         os.Getenv("PLATFORM_RELEASE"),
		AlertEvaluationInterval: time.Duration(envInt("ALERT_EVALUATION_INTERVAL_SEC", 10)) * time.Second,
		AlertStreamMode:         strings.ToLower(env("ALERT_STREAM_MODE", "disabled")),
		AlertStreamKafkaBrokers: splitCSV(firstEnv("ALERT_STREAM_KAFKA_BROKERS", "KAFKA_BROKERS")),
		AlertStreamKafkaTopics:  splitCSV(env("ALERT_STREAM_KAFKA_TOPICS", "vehicle.fields.go.gb32960.v1,vehicle.fields.go.jt808.v1,vehicle.fields.go.yutong-mqtt.v1")),
		AlertStreamKafkaGroup:   env("ALERT_STREAM_KAFKA_GROUP", "vehicle-alert-stream-v1"),
		AlertStreamBatchSize:    envInt("ALERT_STREAM_BATCH_SIZE", 200),
		AlertStreamBatchWait:    time.Duration(envInt("ALERT_STREAM_BATCH_WAIT_MS", 100)) * time.Millisecond,
		AlertStreamLateness:     time.Duration(envInt("ALERT_STREAM_LATENESS_SEC", 120)) * time.Second,
	}
}

func firstEnv(keys ...string) string {
	for _, key := range keys {
		if value := os.Getenv(key); value != "" {
			return value
		}
	}
	return ""
}

func splitCSV(raw string) []string {
	parts := strings.Split(raw, ",")
	values := make([]string, 0, len(parts))
	seen := map[string]bool{}
	for _, part := range parts {
		part = strings.TrimSpace(part)
		if part != "" && !seen[part] {
			seen[part] = true
			values = append(values, part)
		}
	}
	return values
}

func dataMode() string {
	if value := os.Getenv("DATA_MODE"); value != "" {
		return value
	}
	if os.Getenv("MYSQL_DSN") != "" {
		return "production"
	}
	return "mock"
}

func authMode() string {
	if value := os.Getenv("AUTH_MODE"); value != "" {
		return value
	}
	if os.Getenv("AUTH_TOKEN") != "" || os.Getenv("AUTH_TOKENS_JSON") != "" {
		return "enforce"
	}
	return "disabled"
}

func env(key, fallback string) string {
	if value := os.Getenv(key); value != "" {
		return value
	}
	return fallback
}

func envInt(key string, fallback int) int {
	raw := os.Getenv(key)
	if raw == "" {
		return fallback
	}
	value, err := strconv.Atoi(raw)
	if err != nil {
		return fallback
	}
	return value
}
