package db

import (
	"path/filepath"
	"testing"
)

func TestOpenMigratesAndSeeds(t *testing.T) {
	path := filepath.Join(t.TempDir(), "test.db")

	d, err := Open(path)
	if err != nil {
		t.Fatalf("first open: %v", err)
	}

	// Local user is seeded.
	var email string
	if err := d.QueryRow(`SELECT email FROM users WHERE id = ?`, LocalUserID).Scan(&email); err != nil {
		t.Fatalf("local user not seeded: %v", err)
	}

	// All expected tables exist.
	for _, table := range []string{"users", "documents", "suggestions", "plagiarism_reports", "schema_migrations"} {
		var name string
		err := d.QueryRow(`SELECT name FROM sqlite_master WHERE type='table' AND name=?`, table).Scan(&name)
		if err != nil {
			t.Errorf("table %q missing: %v", table, err)
		}
	}

	// The voice suggestion type is permitted by the CHECK constraint.
	if _, err := d.Exec(`INSERT INTO documents (id, user_id) VALUES ('d1', ?)`, LocalUserID); err != nil {
		t.Fatalf("insert document: %v", err)
	}
	if _, err := d.Exec(
		`INSERT INTO suggestions (doc_id, from_pos, to_pos, original, replacement, explanation, type)
		 VALUES ('d1', 0, 4, 'teh', '', 'voice flag', 'voice')`,
	); err != nil {
		t.Fatalf("insert voice suggestion: %v", err)
	}

	// The collocation type (added by migration 0005's table rebuild) is permitted.
	if _, err := d.Exec(
		`INSERT INTO suggestions (doc_id, from_pos, to_pos, original, replacement, explanation, type)
		 VALUES ('d1', 0, 9, 'do a decision', 'make a decision', 'natives usually say…', 'collocation')`,
	); err != nil {
		t.Fatalf("insert collocation suggestion: %v", err)
	}

	// An invalid type is rejected.
	if _, err := d.Exec(
		`INSERT INTO suggestions (doc_id, from_pos, to_pos, original, replacement, explanation, type)
		 VALUES ('d1', 0, 4, 'teh', 'the', 'x', 'nonsense')`,
	); err == nil {
		t.Error("expected CHECK constraint to reject invalid suggestion type")
	}

	// Cascade delete removes child suggestions (foreign keys enabled).
	if _, err := d.Exec(`DELETE FROM documents WHERE id = 'd1'`); err != nil {
		t.Fatalf("delete document: %v", err)
	}
	var n int
	if err := d.QueryRow(`SELECT COUNT(*) FROM suggestions WHERE doc_id = 'd1'`).Scan(&n); err != nil {
		t.Fatal(err)
	}
	if n != 0 {
		t.Errorf("expected cascade delete, got %d orphan suggestions", n)
	}
	d.Close()

	// Re-opening is idempotent: migrations and seed don't double-apply or error.
	d2, err := Open(path)
	if err != nil {
		t.Fatalf("second open: %v", err)
	}
	defer d2.Close()

	var users int
	if err := d2.QueryRow(`SELECT COUNT(*) FROM users WHERE id = ?`, LocalUserID).Scan(&users); err != nil {
		t.Fatal(err)
	}
	if users != 1 {
		t.Errorf("expected exactly 1 local user after reopen, got %d", users)
	}
}
