package config

import (
	"strings"
	"testing"
	"time"
)

// setEnv sets env vars for the test and clears them afterward, so cases don't
// leak into one another. t.Setenv handles restoration.
func setEnv(t *testing.T, kv map[string]string) {
	t.Helper()
	for k, v := range kv {
		t.Setenv(k, v)
	}
}

func TestLoad_AppliesDefaults(t *testing.T) {
	// Clear the ones with defaults so we observe the fallback, not the host env.
	setEnv(t, map[string]string{
		"TAPIR_GATEWAY_URL":         "",
		"TAPIR_SUMMARIZER_MODEL":    "",
		"TAPIR_YT_TOKEN_REF":        "",
		"TAPIR_OAUTH_REDIRECT_ADDR": "",
		"TAPIR_SUMMARIZER_TIMEOUT":  "",
		"TAPIR_POLL_INTERVAL":       "",
	})

	c, err := Load()
	if err != nil {
		t.Fatalf("Load: %v", err)
	}
	if c.GatewayURL != defaultGatewayURL {
		t.Errorf("GatewayURL = %q, want default %q", c.GatewayURL, defaultGatewayURL)
	}
	if c.SummarizerModel != defaultSummarizerModel {
		t.Errorf("SummarizerModel = %q, want default %q", c.SummarizerModel, defaultSummarizerModel)
	}
	if c.YTTokenRef != defaultYTTokenRef {
		t.Errorf("YTTokenRef = %q, want default %q", c.YTTokenRef, defaultYTTokenRef)
	}
	if c.SummarizerTimeout != defaultSummarizerTimeout {
		t.Errorf("SummarizerTimeout = %v, want default %v", c.SummarizerTimeout, defaultSummarizerTimeout)
	}
	if c.PollInterval != 0 {
		t.Errorf("PollInterval = %v, want 0 (run once)", c.PollInterval)
	}
}

func TestLoad_ParsesValues(t *testing.T) {
	setEnv(t, map[string]string{
		"TAPIR_USER_ID":            "11111111-1111-1111-1111-111111111111",
		"TAPIR_GATEWAY_URL":        "http://example/v1",
		"TAPIR_GATEWAY_KEY":        "sk-test",
		"TAPIR_SUMMARIZER_MODEL":   "iguana/deepseek-r1-14b",
		"TAPIR_SUMMARIZER_TIMEOUT": "90s",
		"TAPIR_DB_DSN":             "postgres://x",
		"TAPIR_POLL_INTERVAL":      "10m",
	})

	c, err := Load()
	if err != nil {
		t.Fatalf("Load: %v", err)
	}
	if c.UserID != "11111111-1111-1111-1111-111111111111" {
		t.Errorf("UserID = %q", c.UserID)
	}
	if c.GatewayKey != "sk-test" {
		t.Errorf("GatewayKey = %q", c.GatewayKey)
	}
	if c.SummarizerModel != "iguana/deepseek-r1-14b" {
		t.Errorf("SummarizerModel = %q", c.SummarizerModel)
	}
	if c.SummarizerTimeout != 90*time.Second {
		t.Errorf("SummarizerTimeout = %v, want 90s", c.SummarizerTimeout)
	}
	if c.PollInterval != 10*time.Minute {
		t.Errorf("PollInterval = %v, want 10m", c.PollInterval)
	}
}

func TestLoad_RejectsBadDuration(t *testing.T) {
	setEnv(t, map[string]string{"TAPIR_SUMMARIZER_TIMEOUT": "not-a-duration"})
	if _, err := Load(); err == nil {
		t.Fatal("want error on unparsable duration, got nil")
	}
}

func TestValidateForRun_ReportsMissing(t *testing.T) {
	c := Config{} // nothing set
	err := c.ValidateForRun()
	if err == nil {
		t.Fatal("want error when required run fields are missing")
	}
	for _, want := range []string{"TAPIR_USER_ID", "TAPIR_DB_DSN", "TAPIR_YT_CLIENT_ID"} {
		if !strings.Contains(err.Error(), want) {
			t.Errorf("error %q must name missing field %q", err, want)
		}
	}
}

func TestValidateForAuth_PassesWhenComplete(t *testing.T) {
	c := Config{
		YTClientID:     "id",
		YTClientSecret: "secret",
		YTTokenRef:     "youtube/refresh_token",
		SecretsFile:    "/tmp/secrets.json",
	}
	if err := c.ValidateForAuth(); err != nil {
		t.Errorf("ValidateForAuth: unexpected error %v", err)
	}
}
