package database

import (
	"testing"
)

func TestQArgs_Postgres(t *testing.T) {
	// Force Postgres dialect for test
	CurrentDialect = DialectPostgres
	defer func() { CurrentDialect = DialectSQLite }()

	q, args := QArgs("SELECT * FROM t WHERE a = $1 AND b = $1", "val1")
	if q != "SELECT * FROM t WHERE a = $1 AND b = $1" {
		t.Errorf("Postgres: query should be unchanged, got %q", q)
	}
	if len(args) != 1 {
		t.Errorf("Postgres: args should be unchanged, got %d", len(args))
	}
}

func TestQArgs_SQLite_ReusedPlaceholder(t *testing.T) {
	CurrentDialect = DialectSQLite
	defer func() { CurrentDialect = DialectPostgres }()

	// $1 appears twice — must be expanded to two ? with the same arg value
	q, args := QArgs(
		"SELECT COUNT(*) FROM channels c WHERE c.user_id = $1 OR c.id IN (SELECT channel_id FROM cp WHERE cp.user_id = $1) AND c.is_archived = $2",
		"user-123", false,
	)

	// Should have 3 ? placeholders
	qCount := 0
	for _, c := range q {
		if c == '?' {
			qCount++
		}
	}
	if qCount != 3 {
		t.Errorf("expected 3 ? placeholders, got %d in %q", qCount, q)
	}

	// Should have 3 args: user-123, user-123, false
	if len(args) != 3 {
		t.Fatalf("expected 3 args, got %d: %v", len(args), args)
	}
	if args[0] != "user-123" {
		t.Errorf("args[0] = %v, want user-123", args[0])
	}
	if args[1] != "user-123" {
		t.Errorf("args[1] = %v, want user-123 (expanded from reused $1)", args[1])
	}
	if args[2] != false {
		t.Errorf("args[2] = %v, want false", args[2])
	}

	// Should not contain $N
	if contains(q, "$") {
		t.Errorf("query still contains $: %q", q)
	}
}

func TestQArgs_SQLite_NoReuse(t *testing.T) {
	CurrentDialect = DialectSQLite
	defer func() { CurrentDialect = DialectPostgres }()

	q, args := QArgs("SELECT * FROM t WHERE a = $1 AND b = $2", "a", "b")

	qCount := 0
	for _, c := range q {
		if c == '?' {
			qCount++
		}
	}
	if qCount != 2 {
		t.Errorf("expected 2 ? placeholders, got %d", qCount)
	}
	if len(args) != 2 {
		t.Errorf("expected 2 args, got %d", len(args))
	}
}

func TestQArgs_SQLite_ILIKE(t *testing.T) {
	CurrentDialect = DialectSQLite
	defer func() { CurrentDialect = DialectPostgres }()

	q, _ := QArgs("SELECT * FROM t WHERE name ILIKE $1", "%test%")
	if contains(q, "ILIKE") {
		t.Errorf("ILIKE should be rewritten to LIKE: %q", q)
	}
	if !contains(q, "LIKE") {
		t.Errorf("should contain LIKE: %q", q)
	}
}

func TestQArgs_SQLite_HighPlaceholders(t *testing.T) {
	CurrentDialect = DialectSQLite
	defer func() { CurrentDialect = DialectPostgres }()

	q, args := QArgs(
		"INSERT INTO t (a,b,c,d,e,f,g,h,i,j,k) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11)",
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
	)

	qCount := 0
	for _, c := range q {
		if c == '?' {
			qCount++
		}
	}
	if qCount != 11 {
		t.Errorf("expected 11 ?, got %d in %q", qCount, q)
	}
	if len(args) != 11 {
		t.Errorf("expected 11 args, got %d", len(args))
	}
	// $10 and $11 should not be mangled
	if contains(q, "$") {
		t.Errorf("still contains $: %q", q)
	}
}

func contains(s, substr string) bool {
	for i := 0; i <= len(s)-len(substr); i++ {
		if s[i:i+len(substr)] == substr {
			return true
		}
	}
	return false
}
