package executor

import (
	"context"
	"errors"
	"strings"
	"testing"

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

func TestValidateDMLRejectsNullLiteralInWhereClause(t *testing.T) {
	tests := []struct {
		name string
		cql  string
	}{
		{
			name: "select",
			cql:  "SELECT * FROM ks.tbl WHERE id = NULL",
		},
		{
			name: "update",
			cql:  "UPDATE ks.tbl SET v = 1 WHERE id = NULL",
		},
		{
			name: "delete",
			cql:  "DELETE FROM ks.tbl WHERE id = NULL",
		},
	}

	exec := &dmlExecutor{Executor: &Executor{}}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			stmt, err := parser.NewParser(tt.cql).Parse()
			if err != nil {
				t.Fatalf("parse failed: %v", err)
			}

			err = exec.validateDML(context.Background(), "", "", stmt)
			if err == nil {
				t.Fatalf("expected invalid error")
			}

			var invalidErr *cqlerrors.Error
			if !errors.As(err, &invalidErr) {
				t.Fatalf("expected cqlerrors.Invalid, got %T: %v", err, err)
			}
			if invalidErr.Code() != cqlerrors.CodeInvalid {
				t.Fatalf("expected invalid code, got %d", invalidErr.Code())
			}
			if !strings.Contains(err.Error(), "NULL literal is not allowed in WHERE clause") {
				t.Fatalf("unexpected error message: %v", err)
			}
		})
	}
}

func TestExtractEqualityConditionsRejectsNullLiteralInWhereClause(t *testing.T) {
	stmt, err := parser.NewParser("UPDATE ks.tbl SET v = 1 WHERE id = NULL").Parse()
	if err != nil {
		t.Fatalf("parse failed: %v", err)
	}
	updateStmt, ok := stmt.(*parser.UpdateStatement)
	if !ok {
		t.Fatalf("expected update statement, got %T", stmt)
	}

	_, err = extractEqualityConditions(updateStmt.Where)
	if err == nil {
		t.Fatalf("expected error")
	}
	if !strings.Contains(err.Error(), "NULL literal is not allowed in WHERE clause") {
		t.Fatalf("unexpected error: %v", err)
	}
}
