package collections

import "context"

// CollectionDatabase defines database operations for collections
type CollectionDatabase interface {
	// LoadCollections retrieves all collections from database
	LoadCollections(ctx context.Context) ([]CollectionData, error)

	// LoadCollectionItems retrieves items for a specific collection
	LoadCollectionItems(ctx context.Context, collectionID int32) ([]CollectionItem, error)

	// LoadCollectionRewards retrieves rewards for a specific collection
	LoadCollectionRewards(ctx context.Context, collectionID int32) ([]CollectionRewardData, error)

	// LoadPlayerCollections retrieves player's collection progress
	LoadPlayerCollections(ctx context.Context, characterID int32) ([]PlayerCollectionData, error)

	// LoadPlayerCollectionItems retrieves player's found collection items
	LoadPlayerCollectionItems(ctx context.Context, characterID, collectionID int32) ([]int32, error)

	// SavePlayerCollection saves player collection completion status
	SavePlayerCollection(ctx context.Context, characterID, collectionID int32, completed bool) error

	// SavePlayerCollectionItem saves a found collection item
	SavePlayerCollectionItem(ctx context.Context, characterID, collectionID, itemID int32) error

	// SavePlayerCollections saves all modified player collections
	SavePlayerCollections(ctx context.Context, characterID int32, collections []*Collection) error
}

// ItemLookup provides item information for collections
type ItemLookup interface {
	// GetItem retrieves an item by ID
	GetItem(itemID int32) (ItemInfo, error)

	// ItemExists checks if an item exists
	ItemExists(itemID int32) bool

	// GetItemName returns the name of an item
	GetItemName(itemID int32) string
}

// PlayerManager provides player information for collections
type PlayerManager interface {
	// GetPlayerInfo retrieves basic player information
	GetPlayerInfo(characterID int32) (PlayerInfo, error)

	// IsPlayerOnline checks if a player is currently online
	IsPlayerOnline(characterID int32) bool

	// GetPlayerLevel returns player's current level
	GetPlayerLevel(characterID int32) int8
}

// ClientManager handles client communication for collections
type ClientManager interface {
	// SendCollectionUpdate notifies client of collection changes
	SendCollectionUpdate(characterID int32, collection *Collection) error

	// SendCollectionComplete notifies client of collection completion
	SendCollectionComplete(characterID int32, collection *Collection) error

	// SendCollectionList sends available collections to client
	SendCollectionList(characterID int32, collections []CollectionInfo) error

	// SendCollectionProgress sends collection progress to client
	SendCollectionProgress(characterID int32, progress []CollectionProgress) error
}

// ItemInfo contains item information needed for collections
type ItemInfo struct {
	ID          int32  `json:"id"`
	Name        string `json:"name"`
	Description string `json:"description"`
	Icon        int32  `json:"icon"`
	Level       int8   `json:"level"`
	Rarity      int8   `json:"rarity"`
}

// PlayerInfo contains basic player information
type PlayerInfo struct {
	CharacterID   int32  `json:"character_id"`
	CharacterName string `json:"character_name"`
	Level         int8   `json:"level"`
	Race          int32  `json:"race"`
	Class         int32  `json:"class"`
	IsOnline      bool   `json:"is_online"`
}

// CollectionAware interface for entities that can participate in collections
type CollectionAware interface {
	GetCharacterID() int32
	GetLevel() int8
	HasItem(itemID int32) bool
	GetCollectionList() *PlayerCollectionList
}

// EntityCollectionAdapter adapts entities to work with collection system
type EntityCollectionAdapter struct {
	entity interface {
		GetID() int32
		// Add other entity methods as needed
	}
	playerManager PlayerManager
}

// GetCharacterID returns the character ID from the adapted entity
func (a *EntityCollectionAdapter) GetCharacterID() int32 {
	return a.entity.GetID()
}

// GetLevel returns the character level from player manager
func (a *EntityCollectionAdapter) GetLevel() int8 {
	if info, err := a.playerManager.GetPlayerInfo(a.entity.GetID()); err == nil {
		return info.Level
	}
	return 0
}

// HasItem checks if the character has a specific item (placeholder)
func (a *EntityCollectionAdapter) HasItem(itemID int32) bool {
	// TODO: Implement item checking through entity system
	return false
}

// GetCollectionList placeholder for getting player collection list
func (a *EntityCollectionAdapter) GetCollectionList() *PlayerCollectionList {
	// TODO: Implement collection list retrieval
	return nil
}

// RewardProvider handles collection reward distribution
type RewardProvider interface {
	// GiveItem gives an item to a player
	GiveItem(characterID int32, itemID int32, quantity int8) error

	// GiveCoin gives coins to a player
	GiveCoin(characterID int32, amount int64) error

	// GiveXP gives experience points to a player
	GiveXP(characterID int32, amount int64) error

	// ValidateRewards checks if rewards can be given
	ValidateRewards(characterID int32, rewards []CollectionRewardItem, coin, xp int64) error
}

// CollectionEventHandler handles collection-related events
type CollectionEventHandler interface {
	// OnCollectionStarted called when player starts a collection
	OnCollectionStarted(characterID, collectionID int32)

	// OnItemFound called when player finds a collection item
	OnItemFound(characterID, collectionID, itemID int32)

	// OnCollectionCompleted called when player completes a collection
	OnCollectionCompleted(characterID, collectionID int32)

	// OnRewardClaimed called when player claims collection rewards
	OnRewardClaimed(characterID, collectionID int32, rewards []CollectionRewardItem, coin, xp int64)
}

// LogHandler provides logging functionality
type LogHandler interface {
	// LogDebug logs debug messages
	LogDebug(category, message string, args ...interface{})

	// LogInfo logs informational messages
	LogInfo(category, message string, args ...interface{})

	// LogError logs error messages
	LogError(category, message string, args ...interface{})

	// LogWarning logs warning messages
	LogWarning(category, message string, args ...interface{})
}
