package recipes

import "eq2emu/internal/database"

// RecipeSystemAdapter provides integration interfaces for the recipe system
// Enables seamless integration with player, database, item, and client systems
type RecipeSystemAdapter interface {
	// Player Integration
	GetPlayerRecipeList(characterID int32) *PlayerRecipeList
	GetPlayerRecipeBookList(characterID int32) *PlayerRecipeBookList
	LoadPlayerRecipes(characterID int32) error
	LoadPlayerRecipeBooks(characterID int32) error

	// Recipe Management
	GetRecipe(recipeID int32) *Recipe
	GetRecipeBook(bookID int32) *Recipe
	ValidateRecipe(recipe *Recipe) bool
	CanPlayerUseRecipe(characterID int32, recipeID int32) bool

	// Progress Tracking
	UpdateRecipeProgress(characterID int32, recipeID int32, stage int8) error
	GetRecipeProgress(characterID int32, recipeID int32) int8

	// System Operations
	GetStatistics() RecipeManagerStats
	Validate() []string
	Size() (recipes int32, recipeBooks int32)
}

// DatabaseRecipeAdapter handles database operations for recipes
// Abstracts database interactions for easier testing and multiple database support
type DatabaseRecipeAdapter interface {
	// Recipe Loading
	LoadAllRecipes() ([]*Recipe, error)
	LoadAllRecipeBooks() ([]*Recipe, error)
	LoadRecipeComponents(recipeID int32) (map[int8][]int32, error)

	// Player Recipe Operations
	LoadPlayerRecipes(characterID int32) ([]*Recipe, error)
	LoadPlayerRecipeBooks(characterID int32) ([]*Recipe, error)
	SavePlayerRecipe(characterID int32, recipeID int32) error
	SavePlayerRecipeBook(characterID int32, recipebookID int32) error
	UpdatePlayerRecipe(characterID int32, recipeID int32, highestStage int8) error

	// Validation and Utilities
	RecipeExists(recipeID int32) bool
	RecipeBookExists(bookID int32) bool
	GetRecipesByTier(tier int8) ([]*Recipe, error)
	GetRecipesBySkill(skillID int32) ([]*Recipe, error)
}

// PlayerRecipeAdapter integrates with player management systems
// Provides player-specific recipe functionality and validation
type PlayerRecipeAdapter interface {
	// Player Validation
	PlayerExists(characterID int32) bool
	GetPlayerLevel(characterID int32) int32
	GetPlayerTradeskillLevel(characterID int32, skillID int32) int32
	GetPlayerClass(characterID int32) int8

	// Recipe Access Control
	CanPlayerLearnRecipe(characterID int32, recipeID int32) bool
	CanPlayerUseRecipeBook(characterID int32, bookID int32) bool
	HasPlayerLearnedRecipe(characterID int32, recipeID int32) bool
	HasPlayerRecipeBook(characterID int32, bookID int32) bool

	// Experience and Progression
	AwardTradeskillExperience(characterID int32, skillID int32, experience int32) error
	UpdateTradeskillLevel(characterID int32, skillID int32, level int32) error

	// Notifications
	NotifyRecipeLearned(characterID int32, recipeID int32) error
	NotifyRecipeBookObtained(characterID int32, bookID int32) error
}

// ItemRecipeAdapter integrates with item management systems
// Handles item-related recipe operations and validation
type ItemRecipeAdapter interface {
	// Item Validation
	ItemExists(itemID int32) bool
	GetItemName(itemID int32) string
	GetItemIcon(itemID int32) int16
	GetItemLevel(itemID int32) int32
	IsItemTradeskillTool(itemID int32) bool

	// Recipe Component Validation
	ValidateRecipeComponents(recipeID int32) bool
	GetComponentItemName(itemID int32) string
	GetComponentQuantityRequired(recipeID int32, itemID int32) int16

	// Inventory Integration
	PlayerHasComponents(characterID int32, recipeID int32) bool
	ConsumeRecipeComponents(characterID int32, recipeID int32) error
	AwardRecipeProduct(characterID int32, itemID int32, quantity int8) error

	// Recipe Book Items
	IsRecipeBookItem(itemID int32) bool
	GetRecipeBookRecipes(bookID int32) ([]int32, error)
	ConsumeRecipeBook(characterID int32, bookID int32) error
}

// ClientRecipeAdapter handles client communication for recipes
// Manages packet building and client-side recipe display
type ClientRecipeAdapter interface {
	// Recipe Display
	SendRecipeList(characterID int32) error
	SendRecipeBookList(characterID int32) error
	SendRecipeDetails(characterID int32, recipeID int32) error

	// Recipe Learning
	SendRecipeLearned(characterID int32, recipeID int32) error
	SendRecipeBookObtained(characterID int32, bookID int32) error
	SendRecipeProgress(characterID int32, recipeID int32, stage int8) error

	// Tradeskill Interface
	SendTradeskillWindow(characterID int32, deviceID int32) error
	SendRecipeComponents(characterID int32, recipeID int32) error
	SendCraftingResults(characterID int32, success bool, itemID int32, quantity int8) error

	// Error Messages
	SendRecipeError(characterID int32, errorMessage string) error
	SendInsufficientComponents(characterID int32, recipeID int32) error
	SendInvalidRecipe(characterID int32, recipeID int32) error
}

// EventRecipeAdapter handles recipe-related event processing
// Manages recipe learning, crafting events, and system notifications
type EventRecipeAdapter interface {
	// Recipe Events
	OnRecipeLearned(characterID int32, recipeID int32) error
	OnRecipeBookObtained(characterID int32, bookID int32) error
	OnRecipeCrafted(characterID int32, recipeID int32, success bool) error
	OnCraftingStarted(characterID int32, recipeID int32) error
	OnCraftingCompleted(characterID int32, recipeID int32, stage int8) error

	// Achievement Integration
	CheckCraftingAchievements(characterID int32, recipeID int32) error
	UpdateCraftingStatistics(characterID int32, recipeID int32, success bool) error

	// Guild Integration
	NotifyGuildCrafting(characterID int32, recipeID int32) error
	UpdateGuildCraftingContributions(characterID int32, recipeID int32) error
}

// RecipeAware interface for entities that can interact with recipes
// Provides basic recipe interaction capabilities for players and NPCs
type RecipeAware interface {
	// Recipe Knowledge
	GetKnownRecipes() []int32
	GetRecipeBooks() []int32
	KnowsRecipe(recipeID int32) bool
	HasRecipeBook(bookID int32) bool

	// Recipe Learning
	LearnRecipe(recipeID int32) error
	ObtainRecipeBook(bookID int32) error
	ForgetRecipe(recipeID int32) error

	// Crafting Capabilities
	CanCraftRecipe(recipeID int32) bool
	GetCraftingLevel(skillID int32) int32
	GetMaxCraftingStage(recipeID int32) int8
}

// CraftingRecipeAdapter integrates with crafting system
// Handles active crafting sessions and recipe execution
type CraftingRecipeAdapter interface {
	// Crafting Session Management
	StartCraftingSession(characterID int32, recipeID int32, deviceID int32) error
	ProcessCraftingStage(characterID int32, stage int8) error
	CompleteCraftingSession(characterID int32, success bool) error
	CancelCraftingSession(characterID int32) error

	// Crafting Validation
	ValidateCraftingDevice(deviceID int32, recipeID int32) bool
	ValidateCraftingComponents(characterID int32, recipeID int32) bool
	ValidateCraftingSkill(characterID int32, recipeID int32) bool

	// Progress Tracking
	GetCraftingProgress(characterID int32) (recipeID int32, stage int8, success bool)
	UpdateCraftingStage(characterID int32, stage int8) error

	// Resource Management
	ConsumeCraftingResources(characterID int32, recipeID int32, stage int8) error
	AwardCraftingProducts(characterID int32, recipeID int32, stage int8) error
	CalculateCraftingSuccess(characterID int32, recipeID int32, stage int8) bool
}

// RecipeSystemDependencies aggregates all recipe system dependencies
// Provides a single interface for system-wide recipe functionality
type RecipeSystemDependencies struct {
	Database     DatabaseRecipeAdapter
	Player       PlayerRecipeAdapter
	Item         ItemRecipeAdapter
	Client       ClientRecipeAdapter
	Event        EventRecipeAdapter
	Crafting     CraftingRecipeAdapter
	RecipeSystem RecipeSystemAdapter
}

// RecipeManagerAdapter provides high-level recipe management operations
// Simplifies recipe system access for external systems
type RecipeManagerAdapter struct {
	manager      *RecipeManager
	dependencies *RecipeSystemDependencies
}

// NewRecipeManagerAdapter creates a new recipe manager adapter with dependencies
func NewRecipeManagerAdapter(db *database.DB, deps *RecipeSystemDependencies) *RecipeManagerAdapter {
	return &RecipeManagerAdapter{
		manager:      NewRecipeManager(db),
		dependencies: deps,
	}
}

// GetManager returns the underlying recipe manager
func (rma *RecipeManagerAdapter) GetManager() *RecipeManager {
	return rma.manager
}

// GetDependencies returns the system dependencies
func (rma *RecipeManagerAdapter) GetDependencies() *RecipeSystemDependencies {
	return rma.dependencies
}

// Initialize loads all recipes and recipe books from the database
func (rma *RecipeManagerAdapter) Initialize() error {
	if err := rma.manager.LoadRecipes(); err != nil {
		return err
	}
	return rma.manager.LoadRecipeBooks()
}

// PlayerLearnRecipe handles complete recipe learning workflow
func (rma *RecipeManagerAdapter) PlayerLearnRecipe(characterID int32, recipeID int32) error {
	// Validate recipe exists
	recipe := rma.manager.GetRecipe(recipeID)
	if recipe == nil {
		return ErrRecipeNotFound
	}

	// Check player can learn recipe
	if rma.dependencies.Player != nil {
		if !rma.dependencies.Player.CanPlayerLearnRecipe(characterID, recipeID) {
			return ErrCannotLearnRecipe
		}
	}

	// Save recipe to database
	if err := rma.manager.SavePlayerRecipe(characterID, recipeID); err != nil {
		return err
	}

	// Notify client
	if rma.dependencies.Client != nil {
		if err := rma.dependencies.Client.SendRecipeLearned(characterID, recipeID); err != nil {
			return err
		}
	}

	// Fire event
	if rma.dependencies.Event != nil {
		return rma.dependencies.Event.OnRecipeLearned(characterID, recipeID)
	}

	return nil
}

// PlayerObtainRecipeBook handles complete recipe book acquisition workflow
func (rma *RecipeManagerAdapter) PlayerObtainRecipeBook(characterID int32, bookID int32) error {
	// Validate recipe book exists
	book := rma.manager.GetRecipeBook(bookID)
	if book == nil {
		return ErrRecipeBookNotFound
	}

	// Check player can use recipe book
	if rma.dependencies.Player != nil {
		if !rma.dependencies.Player.CanPlayerUseRecipeBook(characterID, bookID) {
			return ErrCannotUseRecipeBook
		}
	}

	// Save recipe book to database
	if err := rma.manager.SavePlayerRecipeBook(characterID, bookID); err != nil {
		return err
	}

	// Consume recipe book item
	if rma.dependencies.Item != nil {
		if err := rma.dependencies.Item.ConsumeRecipeBook(characterID, bookID); err != nil {
			return err
		}
	}

	// Notify client
	if rma.dependencies.Client != nil {
		if err := rma.dependencies.Client.SendRecipeBookObtained(characterID, bookID); err != nil {
			return err
		}
	}

	// Fire event
	if rma.dependencies.Event != nil {
		return rma.dependencies.Event.OnRecipeBookObtained(characterID, bookID)
	}

	return nil
}

// ValidateRecipeSystem performs comprehensive system validation
func (rma *RecipeManagerAdapter) ValidateRecipeSystem() []string {
	issues := rma.manager.Validate()

	// Add dependency validation
	if rma.dependencies == nil {
		issues = append(issues, "recipe system dependencies not configured")
		return issues
	}

	if rma.dependencies.Database == nil {
		issues = append(issues, "database adapter not configured")
	}

	if rma.dependencies.Player == nil {
		issues = append(issues, "player adapter not configured")
	}

	if rma.dependencies.Item == nil {
		issues = append(issues, "item adapter not configured")
	}

	if rma.dependencies.Client == nil {
		issues = append(issues, "client adapter not configured")
	}

	return issues
}
