package db

import "testing"

// These pin the exact SQL each dialect generates. The MySQL side is the part we
// can't exercise against a live server without docker, so asserting the strings
// here proves MySQL output is byte-for-byte what the store layer used before the
// refactor (the SQLite half is additionally exercised against a real engine).

func TestMySQLDialect_SQL(t *testing.T) {
	d := MySQLDialect{}

	if got := d.LockForUpdate(); got != "FOR UPDATE" {
		t.Errorf("LockForUpdate = %q, want %q", got, "FOR UPDATE")
	}

	// No-op upsert (insert-or-ignore) — matches the old provision_idempotency SQL.
	if got := d.Upsert([]string{"idempotency_key"}); got != "ON DUPLICATE KEY UPDATE idempotency_key = idempotency_key" {
		t.Errorf("noop upsert = %q", got)
	}

	// Accumulate upsert — EXCLUDED.col must rewrite to VALUES(col).
	got := d.Upsert([]string{"user_id", "date"},
		"bytes_up = bytes_up + EXCLUDED.bytes_up",
		"minutes_used = minutes_used + EXCLUDED.minutes_used")
	want := "ON DUPLICATE KEY UPDATE bytes_up = bytes_up + VALUES(bytes_up), minutes_used = minutes_used + VALUES(minutes_used)"
	if got != want {
		t.Errorf("accumulate upsert:\n got=%q\nwant=%q", got, want)
	}

	// version bump
	if got := d.Upsert([]string{"id"}, "version = version + 1"); got != "ON DUPLICATE KEY UPDATE version = version + 1" {
		t.Errorf("bump upsert = %q", got)
	}
}

func TestSQLiteDialect_SQL(t *testing.T) {
	d := SQLiteDialect{}

	if got := d.LockForUpdate(); got != "" {
		t.Errorf("LockForUpdate = %q, want empty (BEGIN IMMEDIATE handles locking)", got)
	}

	if got := d.Upsert([]string{"idempotency_key"}); got != "ON CONFLICT(idempotency_key) DO NOTHING" {
		t.Errorf("noop upsert = %q", got)
	}

	got := d.Upsert([]string{"user_id", "date"},
		"bytes_up = bytes_up + EXCLUDED.bytes_up",
		"minutes_used = minutes_used + EXCLUDED.minutes_used")
	want := "ON CONFLICT(user_id, date) DO UPDATE SET bytes_up = bytes_up + EXCLUDED.bytes_up, minutes_used = minutes_used + EXCLUDED.minutes_used"
	if got != want {
		t.Errorf("accumulate upsert:\n got=%q\nwant=%q", got, want)
	}

	if got := d.Upsert([]string{"id"}, "version = version + 1"); got != "ON CONFLICT(id) DO UPDATE SET version = version + 1" {
		t.Errorf("bump upsert = %q", got)
	}
}

func TestDialectFor(t *testing.T) {
	if DialectFor("mysql").Name() != "mysql" {
		t.Error("DialectFor(mysql)")
	}
	if DialectFor("sqlite").Name() != "sqlite" {
		t.Error("DialectFor(sqlite)")
	}
	if DialectFor("").Name() != "mysql" {
		t.Error("DialectFor(empty) should default to mysql")
	}
}
