package translator

import (
	"testing"

	"github.com/everything-on-mysql/cassandra-on-mysql/pkg/cql/parser"
)

func TestTTLRawClauseFromOptionsStringLiteral(t *testing.T) {
	raw, has, err := TTLRawClauseFromOptions(map[string]interface{}{
		TTLRawOptionName: &parser.StringLiteral{Value: "TTL = `created_at` + INTERVAL 30 DAY TTL_ENABLE='ON'"},
	}, false)
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	if !has {
		t.Fatalf("expected %s option", TTLRawOptionName)
	}
	want := "TTL = `created_at` + INTERVAL 30 DAY TTL_ENABLE='ON'"
	if raw != want {
		t.Fatalf("raw = %q, want %q", raw, want)
	}
}

func TestTTLRawClauseFromOptionsRejectsRemoveOnCreate(t *testing.T) {
	_, has, err := TTLRawClauseFromOptions(map[string]interface{}{
		TTLRawOptionName: &parser.StringLiteral{Value: "REMOVE TTL"},
	}, false)
	if !has {
		t.Fatalf("expected %s option", TTLRawOptionName)
	}
	if err == nil {
		t.Fatalf("expected error for REMOVE TTL in CREATE context")
	}
}

func TestTTLRawClauseFromOptionsAllowsRemoveOnAlter(t *testing.T) {
	raw, has, err := TTLRawClauseFromOptions(map[string]interface{}{
		TTLRawOptionName: &parser.StringLiteral{Value: "REMOVE TTL"},
	}, true)
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	if !has {
		t.Fatalf("expected %s option", TTLRawOptionName)
	}
	if raw != "REMOVE TTL" {
		t.Fatalf("raw = %q, want %q", raw, "REMOVE TTL")
	}
}

func TestTTLRawClauseFromOptionsAllowsTTLEnableOnAlter(t *testing.T) {
	raw, has, err := TTLRawClauseFromOptions(map[string]interface{}{
		TTLRawOptionName: &parser.StringLiteral{Value: "TTL_ENABLE = 'OFF'"},
	}, true)
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	if !has {
		t.Fatalf("expected %s option", TTLRawOptionName)
	}
	if raw != "TTL_ENABLE = 'OFF'" {
		t.Fatalf("raw = %q, want %q", raw, "TTL_ENABLE = 'OFF'")
	}
}

func TestTTLRawClauseFromOptionsAllowsTTLJobIntervalOnAlter(t *testing.T) {
	raw, has, err := TTLRawClauseFromOptions(map[string]interface{}{
		TTLRawOptionName: &parser.StringLiteral{Value: "TTL_JOB_INTERVAL = '12h'"},
	}, true)
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	if !has {
		t.Fatalf("expected %s option", TTLRawOptionName)
	}
	if raw != "TTL_JOB_INTERVAL = '12h'" {
		t.Fatalf("raw = %q, want %q", raw, "TTL_JOB_INTERVAL = '12h'")
	}
}

func TestTTLRawClauseFromOptionsRejectsUnsafeTokens(t *testing.T) {
	_, has, err := TTLRawClauseFromOptions(map[string]interface{}{
		TTLRawOptionName: &parser.StringLiteral{Value: "TTL = `ts` + INTERVAL 1 DAY; DROP TABLE t"},
	}, true)
	if !has {
		t.Fatalf("expected %s option", TTLRawOptionName)
	}
	if err == nil {
		t.Fatalf("expected error for forbidden SQL tokens")
	}
}

func TestTTLRawClauseFromOptionsRejectsNonLiteral(t *testing.T) {
	_, has, err := TTLRawClauseFromOptions(map[string]interface{}{
		TTLRawOptionName: &parser.IntegerLiteral{Value: 10},
	}, true)
	if !has {
		t.Fatalf("expected %s option", TTLRawOptionName)
	}
	if err == nil {
		t.Fatalf("expected error for non-string-literal value")
	}
}

func TestTTLRawClauseFromOptionsRejectsTTLEnableOnCreate(t *testing.T) {
	_, has, err := TTLRawClauseFromOptions(map[string]interface{}{
		TTLRawOptionName: &parser.StringLiteral{Value: "TTL_ENABLE = 'ON'"},
	}, false)
	if !has {
		t.Fatalf("expected %s option", TTLRawOptionName)
	}
	if err == nil {
		t.Fatalf("expected error for TTL_ENABLE in CREATE context")
	}
}

func TestTTLRawClauseFromOptionsAllowsAdditionalOptions(t *testing.T) {
	raw, has, err := TTLRawClauseFromOptions(map[string]interface{}{
		TTLRawOptionName: &parser.StringLiteral{Value: "TTL = `ts` + INTERVAL 1 DAY"},
		"comment":        &parser.StringLiteral{Value: "demo"},
	}, false)
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	if !has {
		t.Fatalf("expected %s option", TTLRawOptionName)
	}
	if raw != "TTL = `ts` + INTERVAL 1 DAY" {
		t.Fatalf("raw = %q, want %q", raw, "TTL = `ts` + INTERVAL 1 DAY")
	}
}

func TestTTLRawClauseFromOptionsRejectsRemovedOptionName(t *testing.T) {
	_, has, err := TTLRawClauseFromOptions(map[string]interface{}{
		"tidb_ttl_raw": &parser.StringLiteral{Value: "TTL = `ts` + INTERVAL 1 DAY"},
	}, false)
	if !has {
		t.Fatalf("expected tidb_ttl_raw option to be detected")
	}
	if err == nil {
		t.Fatalf("expected error for removed option name tidb_ttl_raw")
	}
}
