package config

import (
	"log/slog"
	"os"
	"strconv"
	"strings"
)

type Config struct {
	Port            string
	GatewayBaseURL  string
	RateLimitPerMin int
}

// LLMEnv holds LLM config loaded from environment. Used by both CLI and the
// /webhook/wati handler so they share the same env vars and defaults.
type LLMEnv struct {
	APIKey      string
	BaseURL     string
	Model       string
	FastModel   string
	AstraAPIKey string // Astra platform API key (for gateway/tool calls)
}

// LoadLLMFromEnv reads LLM_API_KEY (or OPENAI_API_KEY), LLM_BASE_URL, LLM_MODEL,
// and LLM_FAST_MODEL. If LLM_FAST_MODEL is unset, a fast model is chosen from
// the primary model (e.g. Haiku for Sonnet). Reused by CLI and webhook.
func LoadLLMFromEnv() LLMEnv {
	apiKey := firstNonEmpty(os.Getenv("LLM_API_KEY"), os.Getenv("OPENAI_API_KEY"))
	baseURL := os.Getenv("LLM_BASE_URL")
	model := getEnv("LLM_MODEL", "anthropic/claude-sonnet-4")
	fastModel := os.Getenv("LLM_FAST_MODEL")
	if fastModel == "" {
		lower := strings.ToLower(model)
		switch {
		case strings.Contains(lower, "opus"), strings.Contains(lower, "sonnet"):
			fastModel = "anthropic/claude-3.5-haiku"
		case strings.Contains(lower, "gpt-4o") && !strings.Contains(lower, "mini"):
			fastModel = "gpt-4o-mini"
		case strings.Contains(lower, "gpt-4.1") && !strings.Contains(lower, "mini") && !strings.Contains(lower, "nano"):
			fastModel = "gpt-4.1-mini"
		case strings.Contains(lower, "gemini-2.5-pro"):
			fastModel = strings.Replace(model, "pro", "flash", 1)
		}
	}
	return LLMEnv{APIKey: apiKey, BaseURL: baseURL, Model: model, FastModel: fastModel}
}

func Load() *Config {
	return &Config{
		Port:            getEnv("PORT", "8080"),
		GatewayBaseURL:  getEnv("ASTRA_GATEWAY_BASE_URL", "https://astra-gateway.wati.io"),
		RateLimitPerMin: getEnvInt("RATE_LIMIT_PER_MIN", 60),
	}
}

// SlogLevel is the default slog level for HTTP services (MCP server, webhook).
// Agent/LLM iteration traces use slog.Debug — they only appear when level is Debug.
// Set ASTRA_LOG_LEVEL=debug or ASTRA_LOG_DEBUG=1 to enable verbose internal logs.
func SlogLevel() slog.Level {
	if os.Getenv("ASTRA_LOG_DEBUG") == "1" {
		return slog.LevelDebug
	}
	switch strings.ToLower(strings.TrimSpace(os.Getenv("ASTRA_LOG_LEVEL"))) {
	case "debug":
		return slog.LevelDebug
	case "warn", "warning":
		return slog.LevelWarn
	case "error":
		return slog.LevelError
	default:
		return slog.LevelInfo
	}
}

// DeriveEnvFromGatewayURL infers the OAuth environment from the gateway base URL.
func DeriveEnvFromGatewayURL(gwURL string) string {
	switch {
	case strings.Contains(gwURL, "stage"):
		return "stage"
	case strings.Contains(gwURL, "qa-"):
		return "qa"
	case strings.Contains(gwURL, "watiapp.io"), strings.Contains(gwURL, "dev-"):
		return "dev"
	default:
		return "prod"
	}
}

func firstNonEmpty(vals ...string) string {
	for _, v := range vals {
		if v != "" {
			return v
		}
	}
	return ""
}

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

func getEnvInt(key string, fallback int) int {
	if v := os.Getenv(key); v != "" {
		if n, err := strconv.Atoi(v); err == nil {
			return n
		}
	}
	return fallback
}
