package drops

import (
	"fmt"

	nigiri "git.sharkk.net/Sharkk/Nigiri"
)

// Drop represents a drop item in the game
type Drop struct {
	ID    int    `json:"id"`
	Name  string `json:"name" db:"required"`
	Level int    `json:"level" db:"index"`
	Type  int    `json:"type" db:"index"`
	Att   string `json:"att"`
}

// DropType constants for drop types
const (
	TypeConsumable = 1
)

// Global store
var store *nigiri.BaseStore[Drop]

// Init sets up the Nigiri store and indices
func Init(collection *nigiri.Collection) {
	store = nigiri.NewBaseStore[Drop]()

	// Register custom indices
	store.RegisterIndex("byLevel", nigiri.BuildIntGroupIndex(func(d *Drop) int {
		return d.Level
	}))

	store.RegisterIndex("byType", nigiri.BuildIntGroupIndex(func(d *Drop) int {
		return d.Type
	}))

	store.RegisterIndex("allByID", nigiri.BuildSortedListIndex(func(a, b *Drop) bool {
		return a.ID < b.ID
	}))

	store.RebuildIndices()
}

// GetStore returns the drops store
func GetStore() *nigiri.BaseStore[Drop] {
	if store == nil {
		panic("drops store not initialized - call Initialize first")
	}
	return store
}

// Creates a new Drop with sensible defaults
func New() *Drop {
	return &Drop{
		Name:  "",
		Level: 1,              // Default minimum level
		Type:  TypeConsumable, // Default to consumable
		Att:   "",
	}
}

// Validate checks if drop has valid values
func (d *Drop) Validate() error {
	if d.Name == "" {
		return fmt.Errorf("drop name cannot be empty")
	}
	if d.Level < 1 {
		return fmt.Errorf("drop Level must be at least 1")
	}
	if d.Type < TypeConsumable {
		return fmt.Errorf("invalid drop type: %d", d.Type)
	}
	return nil
}

// CRUD operations
func (d *Drop) Save() error {
	if d.ID == 0 {
		id, err := store.Create(d)
		if err != nil {
			return err
		}
		d.ID = id
		return nil
	}
	return store.Update(d.ID, d)
}

func (d *Drop) Delete() error {
	store.Remove(d.ID)
	return nil
}

// Insert with ID assignment
func (d *Drop) Insert() error {
	id, err := store.Create(d)
	if err != nil {
		return err
	}
	d.ID = id
	return nil
}

// Query functions
func Find(id int) (*Drop, error) {
	drop, exists := store.Find(id)
	if !exists {
		return nil, fmt.Errorf("drop with ID %d not found", id)
	}
	return drop, nil
}

func All() ([]*Drop, error) {
	return store.AllSorted("allByID"), nil
}

func ByLevel(minLevel int) ([]*Drop, error) {
	return store.FilterByIndex("allByID", func(d *Drop) bool {
		return d.Level <= minLevel
	}), nil
}

func ByType(dropType int) ([]*Drop, error) {
	return store.GroupByIndex("byType", dropType), nil
}

// Helper methods
func (d *Drop) IsConsumable() bool {
	return d.Type == TypeConsumable
}

func (d *Drop) TypeName() string {
	switch d.Type {
	case TypeConsumable:
		return "Consumable"
	default:
		return "Unknown"
	}
}

// Legacy compatibility functions (will be removed later)
func LoadData(dataPath string) error {
	// No longer needed - Nigiri handles this
	return nil
}

func SaveData(dataPath string) error {
	// No longer needed - Nigiri handles this
	return nil
}
