package virtualtables

import (
	"fmt"

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

// VirtualTable represents a virtual table definition
//
// PartitionKeys and ClusteringKeys are used for system_virtual_schema metadata.
type VirtualTable struct {
	Name            string             // Full name (e.g., "system_views.clients")
	Keyspace        string             // Keyspace name (e.g., "system_views")
	Table           string             // Table name (e.g., "clients")
	Columns         []types.ColumnInfo // Column schema
	PartitionKeys   []string           // Primary key partition columns
	ClusteringKeys  []string           // Primary key clustering columns
	ClusteringOrder map[string]string  // Column -> ASC/DESC
	Provider        DataProvider       // Data provider function
	Comment         string             // Table description
	IsReadOnly      bool               // Always true for virtual tables
}

// Registry manages all virtual table definitions
type Registry struct {
	tables map[string]*VirtualTable
}

// NewRegistry creates and initializes a virtual table registry
func NewRegistry() *Registry {
	r := &Registry{
		tables: make(map[string]*VirtualTable),
	}
	r.registerBuiltins()
	return r
}

// Register adds a virtual table to the registry
func (r *Registry) Register(vt *VirtualTable) {
	r.tables[vt.Name] = vt
	r.tables[fmt.Sprintf("%s.%s", vt.Keyspace, vt.Table)] = vt
}

// Lookup retrieves a virtual table by name
func (r *Registry) Lookup(name string) (*VirtualTable, bool) {
	vt, ok := r.tables[name]
	return vt, ok
}

// ListAll returns all registered virtual tables
func (r *Registry) ListAll() []*VirtualTable {
	tables := make([]*VirtualTable, 0, len(r.tables)/2)
	seen := make(map[string]bool)
	for _, vt := range r.tables {
		if !seen[vt.Name] {
			tables = append(tables, vt)
			seen[vt.Name] = true
		}
	}
	return tables
}

func (r *Registry) registerBuiltins() {
	providers := r.providerFactories()
	for _, def := range builtinVirtualTableDefs {
		columns := make([]types.ColumnInfo, len(def.Columns))
		for i, col := range def.Columns {
			columns[i] = types.ColumnInfo{
				Keyspace: def.Keyspace,
				Table:    def.Table,
				Name:     col.Name,
				Type:     col.Type,
			}
		}

		fullName := fmt.Sprintf("%s.%s", def.Keyspace, def.Table)
		provider := provideEmpty
		if factory, ok := providers[fullName]; ok {
			provider = factory(columns)
		}

		r.Register(&VirtualTable{
			Name:            fullName,
			Keyspace:        def.Keyspace,
			Table:           def.Table,
			Columns:         columns,
			PartitionKeys:   def.PartitionKeys,
			ClusteringKeys:  def.ClusteringKeys,
			ClusteringOrder: def.ClusteringOrder,
			Provider:        provider,
			Comment:         "",
			IsReadOnly:      true,
		})
	}
}
