package virtualtables

import (
	"sort"

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

// getKeyspaceSchema returns schema for system_virtual_schema.keyspaces
func getKeyspaceSchema(registry *Registry) (*types.QueryResult, error) {
	columns := []types.ColumnInfo{
		{Keyspace: "system_virtual_schema", Table: "keyspaces", Name: "keyspace_name", Type: "text"},
	}

	if registry == nil {
		registry = NewRegistry()
	}
	allTables := registry.ListAll()
	seen := make(map[string]struct{})
	keyspaces := make([]string, 0)
	for _, vt := range allTables {
		if _, ok := seen[vt.Keyspace]; ok {
			continue
		}
		seen[vt.Keyspace] = struct{}{}
		keyspaces = append(keyspaces, vt.Keyspace)
	}
	sort.Strings(keyspaces)

	rows := make([]types.Row, 0, len(keyspaces))
	for _, ks := range keyspaces {
		rows = append(rows, types.Row{
			Values: []interface{}{ks},
		})
	}

	return &types.QueryResult{Columns: columns, Rows: rows}, nil
}

// getTableSchema returns schema for system_virtual_schema.tables
func getTableSchema(registry *Registry) (*types.QueryResult, error) {
	columns := []types.ColumnInfo{
		{Keyspace: "system_virtual_schema", Table: "tables", Name: "keyspace_name", Type: "text"},
		{Keyspace: "system_virtual_schema", Table: "tables", Name: "table_name", Type: "text"},
		{Keyspace: "system_virtual_schema", Table: "tables", Name: "comment", Type: "text"},
	}

	if registry == nil {
		registry = NewRegistry()
	}
	allTables := registry.ListAll()
	sort.Slice(allTables, func(i, j int) bool {
		if allTables[i].Keyspace == allTables[j].Keyspace {
			return allTables[i].Table < allTables[j].Table
		}
		return allTables[i].Keyspace < allTables[j].Keyspace
	})

	rows := make([]types.Row, 0)
	for _, vt := range allTables {
		rows = append(rows, types.Row{
			Values: []interface{}{
				vt.Keyspace,
				vt.Table,
				vt.Comment,
			},
		})
	}

	return &types.QueryResult{Columns: columns, Rows: rows}, nil
}

// getColumnSchema returns schema for system_virtual_schema.columns
func getColumnSchema(registry *Registry) (*types.QueryResult, error) {
	columns := []types.ColumnInfo{
		{Keyspace: "system_virtual_schema", Table: "columns", Name: "keyspace_name", Type: "text"},
		{Keyspace: "system_virtual_schema", Table: "columns", Name: "table_name", Type: "text"},
		{Keyspace: "system_virtual_schema", Table: "columns", Name: "column_name", Type: "text"},
		{Keyspace: "system_virtual_schema", Table: "columns", Name: "clustering_order", Type: "text"},
		{Keyspace: "system_virtual_schema", Table: "columns", Name: "column_name_bytes", Type: "blob"},
		{Keyspace: "system_virtual_schema", Table: "columns", Name: "kind", Type: "text"},
		{Keyspace: "system_virtual_schema", Table: "columns", Name: "position", Type: "int"},
		{Keyspace: "system_virtual_schema", Table: "columns", Name: "type", Type: "text"},
	}

	if registry == nil {
		registry = NewRegistry()
	}
	allTables := registry.ListAll()
	sort.Slice(allTables, func(i, j int) bool {
		if allTables[i].Keyspace == allTables[j].Keyspace {
			return allTables[i].Table < allTables[j].Table
		}
		return allTables[i].Keyspace < allTables[j].Keyspace
	})

	rows := make([]types.Row, 0)
	for _, vt := range allTables {
		for _, col := range vt.Columns {
			kind, position, order := columnKind(vt, col.Name)
			rows = append(rows, types.Row{
				Values: []interface{}{
					vt.Keyspace,
					vt.Table,
					col.Name,
					order,
					[]byte(col.Name),
					kind,
					position,
					col.Type,
				},
			})
		}
	}

	return &types.QueryResult{Columns: columns, Rows: rows}, nil
}

func columnKind(table *VirtualTable, name string) (string, int, string) {
	for i, pk := range table.PartitionKeys {
		if pk == name {
			return "partition_key", i, "NONE"
		}
	}
	for i, ck := range table.ClusteringKeys {
		if ck == name {
			order := "ASC"
			if table.ClusteringOrder != nil {
				if v, ok := table.ClusteringOrder[ck]; ok {
					order = v
				}
			}
			return "clustering", i, order
		}
	}
	return "regular", -1, "NONE"
}
