package config

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

func validConfig() Config {
	return Config{
		Listen: "127.0.0.1:8095",
		SMTP: SMTPConfig{
			Host:          "mail.virebent.art",
			Port:          587,
			Recipient:     "mail2news@mail2news.tcpreset.net",
			EnvelopeFrom:  "n2usenet@virebent.art",
			Sender:        "n2usenet@virebent.art",
			TLSServerName: "mail.virebent.art",
			RequireTLS:    true,
			ProbeInterval: 15 * time.Minute,
		},
		Security: SecurityConfig{
			MinHashcashBits: 20,
			MinMessageBytes: 10,
			MaxMessageBytes: 65536,
			MaxNewsgroups:   3,
			RateLimitCount:  10,
			RateLimitWindow: time.Hour,
			IdenticonsCLI:   "/usr/local/bin/identicons-cli",
			RequireFace:     true,
		},
	}
}

func TestLoadAcceptsLegacyHeaderFromAsSender(t *testing.T) {
	t.Setenv("N2U_SMTP_HEADER_FROM", "legacy-sender@virebent.art")

	cfg, err := Load()
	if err != nil {
		t.Fatalf("Load returned error: %v", err)
	}
	if got, want := cfg.SMTP.Sender, "legacy-sender@virebent.art"; got != want {
		t.Fatalf("Sender = %q, want %q", got, want)
	}
}

func TestLoadPrefersSenderOverLegacyHeaderFrom(t *testing.T) {
	t.Setenv("N2U_SMTP_SENDER", "sender@virebent.art")
	t.Setenv("N2U_SMTP_HEADER_FROM", "legacy-sender@virebent.art")

	cfg, err := Load()
	if err != nil {
		t.Fatalf("Load returned error: %v", err)
	}
	if got, want := cfg.SMTP.Sender, "sender@virebent.art"; got != want {
		t.Fatalf("Sender = %q, want %q", got, want)
	}
}

func TestValidateSMTPAuthentication(t *testing.T) {
	tests := []struct {
		name    string
		mutate  func(*Config)
		wantErr string
	}{
		{
			name: "credentials with STARTTLS",
			mutate: func(cfg *Config) {
				cfg.SMTP.Username = "n2usenet@virebent.art"
				cfg.SMTP.Password = "test-password"
			},
		},
		{
			name: "missing password",
			mutate: func(cfg *Config) {
				cfg.SMTP.Username = "n2usenet@virebent.art"
			},
			wantErr: "must be configured together",
		},
		{
			name: "missing username",
			mutate: func(cfg *Config) {
				cfg.SMTP.Password = "test-password"
			},
			wantErr: "must be configured together",
		},
		{
			name: "credentials without TLS",
			mutate: func(cfg *Config) {
				cfg.SMTP.Username = "n2usenet@virebent.art"
				cfg.SMTP.Password = "test-password"
				cfg.SMTP.RequireTLS = false
			},
			wantErr: "requires TLS",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			cfg := validConfig()
			tt.mutate(&cfg)
			err := cfg.Validate()
			if tt.wantErr == "" {
				if err != nil {
					t.Fatalf("Validate returned error: %v", err)
				}
				return
			}
			if err == nil || !strings.Contains(err.Error(), tt.wantErr) {
				t.Fatalf("Validate error = %v, want substring %q", err, tt.wantErr)
			}
		})
	}
}

func TestLoadReadsSMTPPasswordFile(t *testing.T) {
	passwordPath := filepath.Join(t.TempDir(), "smtp-password")
	if err := os.WriteFile(passwordPath, []byte("test-password\n"), 0600); err != nil {
		t.Fatalf("write password file: %v", err)
	}
	t.Setenv("N2U_SMTP_USERNAME", "n2usenet@virebent.art")
	t.Setenv("N2U_SMTP_PASSWORD_FILE", passwordPath)
	t.Setenv("N2U_SMTP_REQUIRE_TLS", "true")

	cfg, err := Load()
	if err != nil {
		t.Fatalf("Load returned error: %v", err)
	}
	if got, want := cfg.SMTP.Password, "test-password"; got != want {
		t.Fatalf("Password = %q, want %q", got, want)
	}
}

func TestLoadReadsPersistentCSRFKey(t *testing.T) {
	keyPath := filepath.Join(t.TempDir(), "csrf-key")
	want := strings.Repeat("k", 32)
	if err := os.WriteFile(keyPath, []byte(want+"\n"), 0600); err != nil {
		t.Fatalf("write CSRF key file: %v", err)
	}
	t.Setenv("N2U_CSRF_KEY_FILE", keyPath)

	cfg, err := Load()
	if err != nil {
		t.Fatalf("Load returned error: %v", err)
	}
	if got := string(cfg.Security.CSRFKey); got != want {
		t.Fatalf("CSRFKey = %q, want %q", got, want)
	}
}
