package report

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

	"adguard-shield/internal/config"
	"adguard-shield/internal/db"
)

func TestGenerateUsesTemplatesAndFullStats(t *testing.T) {
	t.Setenv("ADGUARD_SHIELD_SKIP_UPDATE_CHECK", "true")
	store, err := db.Open(filepath.Join(t.TempDir(), "report.db"))
	if err != nil {
		t.Fatal(err)
	}
	defer store.Close()

	yesterday := midnight(time.Now()).AddDate(0, 0, -1).Add(12 * time.Hour)
	events := []struct {
		ip       string
		domain   string
		duration string
		proto    string
		reason   string
	}{
		{"1.2.3.4", "example.com", "3600s", "DNS", "rate-limit"},
		{"1.2.3.4", "example.com", "permanent", "DoH", "subdomain-flood"},
		{"5.6.7.8", "block.example", "permanent", "DoT", "external-blocklist"},
	}
	for i, e := range events {
		ts := yesterday.Add(time.Duration(i) * time.Hour)
		_, err := store.DB.Exec(`INSERT INTO ban_history (timestamp_epoch, timestamp_text, action, client_ip, domain, count, duration, protocol, reason) VALUES (?, ?, 'BAN', ?, ?, '42', ?, ?, ?)`,
			ts.Unix(), ts.Format("2006-01-02 15:04:05"), e.ip, e.domain, e.duration, e.proto, e.reason)
		if err != nil {
			t.Fatal(err)
		}
	}
	ts := yesterday.Add(4 * time.Hour)
	if _, err := store.DB.Exec(`INSERT INTO ban_history (timestamp_epoch, timestamp_text, action, client_ip, domain, count, duration, protocol, reason) VALUES (?, ?, 'UNBAN', '1.2.3.4', '-', '-', '-', '-', 'manual')`, ts.Unix(), ts.Format("2006-01-02 15:04:05")); err != nil {
		t.Fatal(err)
	}
	if err := store.InsertBan(db.Ban{IP: "5.6.7.8", Domain: "block.example", Permanent: true, Reason: "external-blocklist", Protocol: "DoT", Source: "external-blocklist"}); err != nil {
		t.Fatal(err)
	}

	logPath := filepath.Join(t.TempDir(), "shield.log")
	if err := writeTestLog(logPath, yesterday); err != nil {
		t.Fatal(err)
	}
	cfg := &config.Config{
		Path:                  filepath.Join(t.TempDir(), "adguard-shield.conf"),
		ReportInterval:        "weekly",
		ReportFormat:          "html",
		ReportBusiestDayRange: 30,
		LogFile:               logPath,
		ReportEmailTo:         "admin@example.test",
		ReportEmailFrom:       "shield@example.test",
		ReportMailCmd:         "msmtp",
	}

	htmlReport, err := Generate(cfg, store, "html")
	if err != nil {
		t.Fatal(err)
	}
	for _, want := range []string{"AdGuard Shield", "example.com", "1.2.3.4", "DoH", "Subdomain-Flood Sperren", "AbuseIPDB Reports"} {
		if !strings.Contains(htmlReport, want) {
			t.Fatalf("HTML report missing %q\n%s", want, htmlReport)
		}
	}
	if strings.Contains(htmlReport, "{{") {
		t.Fatalf("HTML report still contains placeholders")
	}

	txtReport, err := Generate(cfg, store, "txt")
	if err != nil {
		t.Fatal(err)
	}
	for _, want := range []string{"Sperren gesamt:          3", "Entsperrungen:           1", "Permanente Sperren:      2", "block.example"} {
		if !strings.Contains(txtReport, want) {
			t.Fatalf("TXT report missing %q\n%s", want, txtReport)
		}
	}
}

func TestVersionGreater(t *testing.T) {
	tests := []struct {
		a, b string
		want bool
	}{
		{"v1.0.1", "v1.0.0", true},
		{"v1.0.0", "v1.0.0", false},
		{"v1.2.0", "v1.10.0", false},
	}
	for _, tt := range tests {
		if got := versionGreater(tt.a, tt.b); got != tt.want {
			t.Fatalf("versionGreater(%q, %q) = %v, want %v", tt.a, tt.b, got, tt.want)
		}
	}
}

func writeTestLog(path string, when time.Time) error {
	line := "[" + when.Format("2006-01-02 15:04:05") + "] [INFO] AbuseIPDB: 5.6.7.8 erfolgreich gemeldet\n"
	return os.WriteFile(path, []byte(line), 0644)
}
