package executor

import (
	"testing"
	"time"

	gocql "github.com/apache/cassandra-gocql-driver/v2"
	"github.com/everything-on-mysql/cassandra-on-mysql/pkg/cql/parser"
)

func TestApplyTimeConversionsForDMLBindMarker(t *testing.T) {
	stmt := mustParseStatement(t, "INSERT INTO ks.tbl (ts) VALUES (toTimestamp(?))")
	insertStmt, ok := stmt.(*parser.InsertStatement)
	if !ok {
		t.Fatalf("expected insert statement, got %T", stmt)
	}
	uuid := gocql.TimeUUID()
	params := []interface{}{uuid.String()}
	updated, updatedParams, changed, err := applyTimeConversionsForDML(insertStmt, params, nil)
	if err != nil {
		t.Fatalf("applyTimeConversionsForDML failed: %v", err)
	}
	if !changed {
		t.Fatalf("expected time conversion to change statement")
	}
	updatedInsert, ok := updated.(*parser.InsertStatement)
	if !ok {
		t.Fatalf("expected insert statement, got %T", updated)
	}
	if _, ok := updatedInsert.Values[0][0].(*parser.BindMarker); !ok {
		t.Fatalf("expected bind marker value, got %T", updatedInsert.Values[0][0])
	}
	ts, ok := updatedParams[0].(time.Time)
	if !ok {
		t.Fatalf("expected time.Time param, got %T", updatedParams[0])
	}
	if !ts.UTC().Equal(uuid.Time().UTC()) {
		t.Fatalf("expected %v, got %v", uuid.Time().UTC(), ts.UTC())
	}
}

func TestApplyTimeConversionsForDMLLiteral(t *testing.T) {
	stmt := mustParseStatement(t, "UPDATE ks.tbl SET v = toUnixTimestamp('2024-06-01') WHERE id = 1")
	updateStmt, ok := stmt.(*parser.UpdateStatement)
	if !ok {
		t.Fatalf("expected update statement, got %T", stmt)
	}
	updated, _, changed, err := applyTimeConversionsForDML(updateStmt, nil, nil)
	if err != nil {
		t.Fatalf("applyTimeConversionsForDML failed: %v", err)
	}
	if !changed {
		t.Fatalf("expected time conversion to change statement")
	}
	updatedUpdate, ok := updated.(*parser.UpdateStatement)
	if !ok {
		t.Fatalf("expected update statement, got %T", updated)
	}
	assign := updatedUpdate.Assigments[0]
	lit, ok := assign.Value.(*parser.IntegerLiteral)
	if !ok {
		t.Fatalf("expected integer literal, got %T", assign.Value)
	}
	expected := unixMillis(time.Date(2024, 6, 1, 0, 0, 0, 0, time.UTC))
	if lit.Value != expected {
		t.Fatalf("expected %d, got %d", expected, lit.Value)
	}
}

func TestApplyTimeConversionsForDMLColumnArg(t *testing.T) {
	stmt := mustParseStatement(t, "UPDATE ks.tbl SET v = toDate(ts) WHERE id = 1")
	updateStmt, ok := stmt.(*parser.UpdateStatement)
	if !ok {
		t.Fatalf("expected update statement, got %T", stmt)
	}
	_, _, _, err := applyTimeConversionsForDML(updateStmt, nil, map[string]string{"ts": "timestamp"})
	if err == nil {
		t.Fatalf("expected error for column argument")
	}
}
