package executor

import (
	"context"

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

func (e *dmlExecutor) validateDML(ctx context.Context, user, password string, stmt parser.Statement) error {
	switch s := stmt.(type) {
	case *parser.SelectStatement:
		if err := e.validateTableName(s.From); err != nil {
			return err
		}
		if err := validateQueryWhereClause(s.Where); err != nil {
			return err
		}
		if err := validateOffsetRequiresLimit(s); err != nil {
			return err
		}
		if err := e.ensureUserKeyspace(s.From.Schema); err != nil {
			return err
		}
		if err := e.ensureSchemaExists(ctx, user, password, s.From.Schema); err != nil {
			return err
		}
		if err := e.ensureTableExists(ctx, user, password, s.From.Schema, s.From.Name); err != nil {
			return err
		}
	case *parser.InsertStatement:
		if err := e.validateTableName(s.Table); err != nil {
			return err
		}
		if err := e.ensureUserKeyspace(s.Table.Schema); err != nil {
			return err
		}
		if err := e.ensureSchemaExists(ctx, user, password, s.Table.Schema); err != nil {
			return err
		}
		if err := e.ensureTableExists(ctx, user, password, s.Table.Schema, s.Table.Name); err != nil {
			return err
		}
		for _, col := range s.Columns {
			if err := e.validateColumnName(col); err != nil {
				return err
			}
		}
		if err := e.rejectCounterInsert(ctx, user, password, s); err != nil {
			return err
		}
	case *parser.UpdateStatement:
		if err := e.validateTableName(s.Table); err != nil {
			return err
		}
		if err := validateQueryWhereClause(s.Where); err != nil {
			return err
		}
		if err := e.ensureUserKeyspace(s.Table.Schema); err != nil {
			return err
		}
		if err := e.ensureSchemaExists(ctx, user, password, s.Table.Schema); err != nil {
			return err
		}
		if err := e.ensureTableExists(ctx, user, password, s.Table.Schema, s.Table.Name); err != nil {
			return err
		}
		for _, assignment := range s.Assigments {
			if err := e.validateColumnName(assignment.Column); err != nil {
				return err
			}
		}
	case *parser.DeleteStatement:
		if err := e.validateTableName(s.From); err != nil {
			return err
		}
		if err := validateQueryWhereClause(s.Where); err != nil {
			return err
		}
		if err := e.ensureUserKeyspace(s.From.Schema); err != nil {
			return err
		}
		if err := e.ensureSchemaExists(ctx, user, password, s.From.Schema); err != nil {
			return err
		}
		if err := e.ensureTableExists(ctx, user, password, s.From.Schema, s.From.Name); err != nil {
			return err
		}
	}
	return nil
}
