package config

import (
	"os"
	"path/filepath"
	"strings"
	"testing"
	"time"
)

func TestResolvePathPrecedence(t *testing.T) {
	t.Setenv("AMCS_CONFIG", "/tmp/from-env.yaml")

	if got := ResolvePath("/tmp/explicit.yaml"); got != "/tmp/explicit.yaml" {
		t.Fatalf("ResolvePath explicit = %q, want %q", got, "/tmp/explicit.yaml")
	}

	if got := ResolvePath(""); got != "/tmp/from-env.yaml" {
		t.Fatalf("ResolvePath env = %q, want %q", got, "/tmp/from-env.yaml")
	}
}

func TestResolvePathIgnoresBareYAMLExtension(t *testing.T) {
	t.Setenv("AMCS_CONFIG", "/tmp/from-env.yaml")

	if got := ResolvePath(".yaml"); got != "/tmp/from-env.yaml" {
		t.Fatalf("ResolvePath(.yaml) = %q, want %q", got, "/tmp/from-env.yaml")
	}

	if got := ResolvePath(".yml"); got != "/tmp/from-env.yaml" {
		t.Fatalf("ResolvePath(.yml) = %q, want %q", got, "/tmp/from-env.yaml")
	}
}

const v2ConfigYAML = `
version: 2
server:
  port: 8080
mcp:
  path: "/mcp"
  session_timeout: "30m"
auth:
  keys:
    - id: "test"
      value: "secret"
database:
  url: "postgres://from-file"
ai:
  providers:
    default:
      type: "litellm"
      base_url: "http://localhost:4000/v1"
      api_key: "file-key"
  embeddings:
    dimensions: 1536
    primary:
      provider: "default"
      model: "text-embed"
  metadata:
    primary:
      provider: "default"
      model: "gpt-4"
search:
  default_limit: 10
  max_limit: 50
logging:
  level: "info"
`

func TestLoadAppliesEnvOverrides(t *testing.T) {
	configPath := filepath.Join(t.TempDir(), "test.yaml")
	if err := os.WriteFile(configPath, []byte(v2ConfigYAML), 0o600); err != nil {
		t.Fatalf("write config: %v", err)
	}

	t.Setenv("AMCS_DATABASE_URL", "postgres://from-env")
	t.Setenv("AMCS_LITELLM_API_KEY", "env-key")
	t.Setenv("AMCS_SERVER_PORT", "9090")

	cfg, loadedFrom, err := Load(configPath)
	if err != nil {
		t.Fatalf("Load() error = %v", err)
	}

	if loadedFrom != configPath {
		t.Fatalf("loadedFrom = %q, want %q", loadedFrom, configPath)
	}
	if cfg.Database.URL != "postgres://from-env" {
		t.Fatalf("database url = %q, want env override", cfg.Database.URL)
	}
	if cfg.AI.Providers["default"].APIKey != "env-key" {
		t.Fatalf("litellm api key = %q, want env override", cfg.AI.Providers["default"].APIKey)
	}
	if cfg.Server.Port != 9090 {
		t.Fatalf("server port = %d, want 9090", cfg.Server.Port)
	}
	if cfg.MCP.SessionTimeout != 30*time.Minute {
		t.Fatalf("mcp session timeout = %v, want 30m", cfg.MCP.SessionTimeout)
	}
}

func TestLoadAppliesOllamaEnvOverrides(t *testing.T) {
	configPath := filepath.Join(t.TempDir(), "test.yaml")
	if err := os.WriteFile(configPath, []byte(`
version: 2
server:
  port: 8080
mcp:
  path: "/mcp"
  session_timeout: "10m"
auth:
  keys:
    - id: "test"
      value: "secret"
database:
  url: "postgres://from-file"
ai:
  providers:
    local:
      type: "ollama"
      base_url: "http://localhost:11434/v1"
      api_key: "ollama"
  embeddings:
    dimensions: 768
    primary:
      provider: "local"
      model: "nomic-embed-text"
  metadata:
    primary:
      provider: "local"
      model: "llama3.2"
search:
  default_limit: 10
  max_limit: 50
logging:
  level: "info"
`), 0o600); err != nil {
		t.Fatalf("write config: %v", err)
	}

	t.Setenv("AMCS_OLLAMA_BASE_URL", "https://ollama.example.com/v1")
	t.Setenv("AMCS_OLLAMA_API_KEY", "remote-key")

	cfg, _, err := Load(configPath)
	if err != nil {
		t.Fatalf("Load() error = %v", err)
	}

	p := cfg.AI.Providers["local"]
	if p.BaseURL != "https://ollama.example.com/v1" {
		t.Fatalf("ollama base url = %q, want env override", p.BaseURL)
	}
	if p.APIKey != "remote-key" {
		t.Fatalf("ollama api key = %q, want env override", p.APIKey)
	}
}

func TestLoadMigratesV1Config(t *testing.T) {
	configPath := filepath.Join(t.TempDir(), "v1.yaml")
	v1 := `
server:
  port: 8080
mcp:
  path: "/mcp"
  session_timeout: "10m"
auth:
  keys:
    - id: "test"
      value: "secret"
database:
  url: "postgres://from-file"
ai:
  provider: "litellm"
  embeddings:
    model: "text-embed"
    dimensions: 1536
  metadata:
    model: "gpt-4"
    temperature: 0.2
    fallback_models: ["gpt-3.5"]
  litellm:
    base_url: "http://localhost:4000/v1"
    api_key: "file-key"
search:
  default_limit: 10
  max_limit: 50
logging:
  level: "info"
`
	if err := os.WriteFile(configPath, []byte(v1), 0o600); err != nil {
		t.Fatalf("write config: %v", err)
	}

	cfg, _, err := Load(configPath)
	if err != nil {
		t.Fatalf("Load() error = %v", err)
	}

	if cfg.Version != CurrentConfigVersion {
		t.Fatalf("version = %d, want %d", cfg.Version, CurrentConfigVersion)
	}
	if p, ok := cfg.AI.Providers["default"]; !ok || p.Type != "litellm" || p.APIKey != "file-key" {
		t.Fatalf("providers[default] = %+v, want litellm/file-key", p)
	}
	if cfg.AI.Embeddings.Primary.Model != "text-embed" || cfg.AI.Embeddings.Primary.Provider != "default" {
		t.Fatalf("embeddings.primary = %+v, want default/text-embed", cfg.AI.Embeddings.Primary)
	}
	if cfg.AI.Metadata.Primary.Model != "gpt-4" || cfg.AI.Metadata.Primary.Provider != "default" {
		t.Fatalf("metadata.primary = %+v, want default/gpt-4", cfg.AI.Metadata.Primary)
	}
	if len(cfg.AI.Metadata.Fallbacks) != 1 || cfg.AI.Metadata.Fallbacks[0].Model != "gpt-3.5" {
		t.Fatalf("metadata.fallbacks = %+v, want [default/gpt-3.5]", cfg.AI.Metadata.Fallbacks)
	}

	entries, err := filepath.Glob(configPath + ".bak.*")
	if err != nil {
		t.Fatalf("glob backups: %v", err)
	}
	if len(entries) != 0 {
		t.Fatalf("backup files = %d, want 0 (load should not rewrite config)", len(entries))
	}

	originalOnDisk, err := os.ReadFile(configPath)
	if err != nil {
		t.Fatalf("read original config: %v", err)
	}
	if !strings.Contains(string(originalOnDisk), "provider: \"litellm\"") {
		t.Fatalf("expected source config to remain unchanged on disk")
	}
}
