package executor

import (
	"strings"

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

func applyDefaultKeyspace(stmt parser.Statement, keyspace string) {
	if stmt == nil || keyspace == "" {
		return
	}

	switch s := stmt.(type) {
	case *parser.SelectStatement:
		applyKeyspaceToTableName(s.From, keyspace)
	case *parser.InsertStatement:
		applyKeyspaceToTableName(s.Table, keyspace)
	case *parser.UpdateStatement:
		applyKeyspaceToTableName(s.Table, keyspace)
	case *parser.DeleteStatement:
		applyKeyspaceToTableName(s.From, keyspace)
	case *parser.CreateTableStatement:
		applyKeyspaceToTableName(s.Name, keyspace)
	case *parser.CreateTableLikeStatement:
		applyKeyspaceToTableName(s.Name, keyspace)
		applyKeyspaceToTableName(s.Source, keyspace)
	case *parser.DropTableStatement:
		applyKeyspaceToTableName(s.Name, keyspace)
	case *parser.CreateIndexStatement:
		applyKeyspaceToTableName(s.Table, keyspace)
	case *parser.AlterTableStatement:
		applyKeyspaceToTableName(s.Table, keyspace)
	case *parser.TruncateStatement:
		applyKeyspaceToTableName(s.Table, keyspace)
	case *parser.CreateTypeStatement:
		applyKeyspaceToTableName(s.Name, keyspace)
	case *parser.AlterTypeStatement:
		applyKeyspaceToTableName(s.Name, keyspace)
	case *parser.DropTypeStatement:
		applyKeyspaceToTableName(s.Name, keyspace)
	case *parser.DropIndexStatement:
		if !strings.Contains(s.Name, ".") {
			s.Name = keyspace + "." + s.Name
		}
	case *parser.CreateMaterializedViewStatement:
		applyKeyspaceToTableName(s.Name, keyspace)
		applyKeyspaceToSelect(s.Select, keyspace)
	case *parser.AlterMaterializedViewStatement:
		applyKeyspaceToTableName(s.Name, keyspace)
	case *parser.DropMaterializedViewStatement:
		applyKeyspaceToTableName(s.Name, keyspace)
	case *parser.CreateTriggerStatement:
		applyKeyspaceToTableName(s.Table, keyspace)
	case *parser.DropTriggerStatement:
		applyKeyspaceToTableName(s.Table, keyspace)
	case *parser.CreateFunctionStatement:
		applyKeyspaceToTableName(s.Name, keyspace)
	case *parser.DropFunctionStatement:
		applyKeyspaceToTableName(s.Name, keyspace)
	case *parser.CreateAggregateStatement:
		applyKeyspaceToTableName(s.Name, keyspace)
		applyKeyspaceToTableName(s.StateFunc, keyspace)
		applyKeyspaceToTableName(s.FinalFunc, keyspace)
	case *parser.DropAggregateStatement:
		applyKeyspaceToTableName(s.Name, keyspace)
	case *parser.BatchStatement:
		for _, entry := range s.Entries {
			applyDefaultKeyspace(entry, keyspace)
		}
	case *parser.DescribeStatement:
		switch s.Target {
		case parser.DescribeTargetTable:
			applyKeyspaceToTableName(s.Table, keyspace)
		case parser.DescribeTargetTables:
			if s.Keyspace == "" {
				s.Keyspace = keyspace
			}
		}
	}
}

// ApplyDefaultKeyspace applies the default keyspace to unqualified table references.
func ApplyDefaultKeyspace(stmt parser.Statement, keyspace string) {
	applyDefaultKeyspace(stmt, keyspace)
}

func applyKeyspaceToSelect(stmt *parser.SelectStatement, keyspace string) {
	if stmt == nil {
		return
	}
	applyKeyspaceToTableName(stmt.From, keyspace)
}

func applyKeyspaceToTableName(name *parser.TableName, keyspace string) {
	if name == nil || keyspace == "" || name.Schema != "" {
		return
	}
	name.Schema = keyspace
}
