package db

import (
	"database/sql"
	"path/filepath"
	"testing"
)

// TestAddAllowBlockJunkEntryWorksAfterMigration reproduces the same class of bug as
// the filter-rules CHECK migrations: a DB created before 'junk' was added to
// esrv_mailbox_allowblock's list_type CHECK constraint (the self-service webmail
// Blocklist feature) kept the old, narrower constraint forever, since SQLite can't
// ALTER a CHECK on an existing table.
func TestAddAllowBlockJunkEntryWorksAfterMigration(t *testing.T) {
	path := filepath.Join(t.TempDir(), "test.db")

	raw, err := sql.Open("sqlite", path)
	if err != nil {
		t.Fatal(err)
	}
	if _, err := raw.Exec(`CREATE TABLE esrv_mailboxes (id INTEGER PRIMARY KEY AUTOINCREMENT)`); err != nil {
		t.Fatal(err)
	}
	if _, err := raw.Exec(`
		CREATE TABLE esrv_mailbox_allowblock (
			id INTEGER PRIMARY KEY AUTOINCREMENT,
			mailbox_id INTEGER NOT NULL REFERENCES esrv_mailboxes(id),
			list_type TEXT NOT NULL CHECK(list_type IN ('allow','block')),
			pattern TEXT NOT NULL,
			created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
			UNIQUE(mailbox_id, list_type, pattern)
		)
	`); err != nil {
		t.Fatal(err)
	}
	if _, err := raw.Exec(`INSERT INTO esrv_mailboxes (id) VALUES (1)`); err != nil {
		t.Fatal(err)
	}
	if _, err := raw.Exec(`
		INSERT INTO esrv_mailbox_allowblock (mailbox_id, list_type, pattern) VALUES (1, 'allow', 'trusted@example.com')
	`); err != nil {
		t.Fatal(err)
	}
	if err := raw.Close(); err != nil {
		t.Fatal(err)
	}

	database, err := Open(path)
	if err != nil {
		t.Fatal(err)
	}
	t.Cleanup(func() { database.Close() })

	if _, err := database.AddAllowBlockEntry(1, "junk", "spammer@example.com"); err != nil {
		t.Fatalf("AddAllowBlockEntry with 'junk' after migrating a legacy DB: %v", err)
	}

	entries, err := database.ListAllowBlock(1)
	if err != nil {
		t.Fatal(err)
	}
	if len(entries) != 2 {
		t.Fatalf("expected the pre-existing allow entry to survive the table rebuild alongside the new junk one, got %d entries", len(entries))
	}
	found := false
	for _, e := range entries {
		if e.ListType == "allow" && e.Pattern == "trusted@example.com" {
			found = true
		}
	}
	if !found {
		t.Fatalf("pre-existing allow entry's data was not preserved across the migration: %+v", entries)
	}

	junked, err := database.IsJunked(1, "spammer@example.com")
	if err != nil || !junked {
		t.Fatalf("expected spammer@example.com to be junked, got junked=%v err=%v", junked, err)
	}
}
