package tradeskills

import (
	"fmt"
	"log"
	"math"
)

// PacketBuilder handles the construction of tradeskill-related packets.
type PacketBuilder interface {
	// SendCreateFromRecipe builds and sends the recipe crafting UI packet
	SendCreateFromRecipe(clientID uint32, recipeID uint32) error

	// SendItemCreationUI builds and sends the item creation/crafting progress UI packet
	SendItemCreationUI(clientID uint32, recipeID uint32) error

	// StopCrafting sends the stop crafting packet
	StopCrafting(clientID uint32) error

	// CounterReaction sends the event counter reaction packet
	CounterReaction(clientID uint32, countered bool) error

	// UpdateCreateItem sends crafting progress update packet
	UpdateCreateItem(clientID uint32, update CraftingUpdate) error
}

// CraftingUpdate represents data for a crafting progress update packet.
type CraftingUpdate struct {
	TableSpawnID     uint32           // ID of the crafting table spawn
	Effect           int8             // Effect type (1=crit success, 2=success, 3=failure, 4=crit failure)
	TotalDurability  int32            // Current total durability
	TotalProgress    int32            // Current total progress
	DurabilityChange int32            // Change in durability this update
	ProgressChange   int32            // Change in progress this update
	ProgressLevel    int8             // Progress level (0-4)
	Event            *TradeskillEvent // Active event (if any)
}

// RecipeComponentInfo represents component information for recipe UI.
type RecipeComponentInfo struct {
	ItemID       uint32 // Item ID
	UniqueID     uint32 // Unique item instance ID
	Name         string // Item name
	Icon         uint32 // Item icon
	Quantity     int16  // Available quantity
	QuantityUsed int16  // Quantity being used
}

// RecipeUIData represents all data needed for the recipe creation UI.
type RecipeUIData struct {
	RecipeID              uint32                  // Recipe ID
	RecipeName            string                  // Recipe name
	CraftingStation       string                  // Required crafting station
	Tier                  int8                    // Recipe tier
	ProductName           string                  // Product name
	ProductIcon           uint32                  // Product icon
	ProductQuantity       int16                   // Product quantity
	PrimaryTitle          string                  // Primary component title
	PrimaryQuantityNeeded int16                   // Primary component quantity needed
	PrimaryComponents     []RecipeComponentInfo   // Available primary components
	PrimarySelected       []RecipeComponentInfo   // Selected primary components
	BuildComponents       [][]RecipeComponentInfo // Build components (slots 1-4)
	BuildSelected         [][]RecipeComponentInfo // Selected build components
	BuildTitles           []string                // Build component titles
	BuildQuantitiesNeeded []int16                 // Build component quantities needed
	FuelTitle             string                  // Fuel component title
	FuelQuantityNeeded    int16                   // Fuel component quantity needed
	FuelComponents        []RecipeComponentInfo   // Available fuel components
	FuelSelected          []RecipeComponentInfo   // Selected fuel components
	MassProductionChoices []int32                 // Mass production quantity choices
}

// ItemCreationUIData represents data for the item creation progress UI.
type ItemCreationUIData struct {
	MaxPossibleDurability int32               // Maximum durability (1000)
	MaxPossibleProgress   int32               // Maximum progress (1000)
	ProductProgressNeeded int32               // Progress needed for completion (1000)
	ProgressLevelsKnown   int8                // Highest stage known by player
	ProcessStages         []ItemCreationStage // Process stages (0-3)
	ProductItem           ItemCreationProduct // Final product
	SkillIDs              []uint32            // Available skill IDs for crafting
}

// ItemCreationStage represents a stage in the item creation process.
type ItemCreationStage struct {
	ProgressNeeded int32               // Progress needed for this stage
	Product        ItemCreationProduct // Product for this stage
	Byproduct      ItemCreationProduct // Byproduct for this stage (optional)
}

// ItemCreationProduct represents a product in item creation.
type ItemCreationProduct struct {
	Name string // Product name
	Icon uint32 // Product icon
}

// DefaultPacketBuilder is a basic implementation of PacketBuilder.
// In a real implementation, this would interface with the actual packet system.
type DefaultPacketBuilder struct {
	// TODO: Add dependencies for actual packet building (client manager, item manager, etc.)
}

// NewDefaultPacketBuilder creates a new default packet builder.
func NewDefaultPacketBuilder() *DefaultPacketBuilder {
	return &DefaultPacketBuilder{}
}

// SendCreateFromRecipe builds and sends the recipe crafting UI packet.
func (pb *DefaultPacketBuilder) SendCreateFromRecipe(clientID uint32, recipeID uint32) error {
	// TODO: Implement actual packet building
	// This is a placeholder implementation showing the data structure

	log.Printf("Building WS_CreateFromRecipe packet for client %d, recipe %d", clientID, recipeID)

	// In the real implementation, this would:
	// 1. Get recipe from master recipe list
	// 2. Validate player has recipe
	// 3. Validate crafting table
	// 4. Build component lists
	// 5. Calculate mass production options
	// 6. Create and send packet

	uiData := RecipeUIData{
		RecipeID:              recipeID,
		RecipeName:            "Example Recipe",
		CraftingStation:       "Forge",
		Tier:                  1,
		ProductName:           "Iron Sword",
		ProductIcon:           12345,
		ProductQuantity:       1,
		PrimaryTitle:          "Metal",
		PrimaryQuantityNeeded: 2,
		MassProductionChoices: []int32{1, 5, 10, 15, 20, 25},
	}

	// Add example primary components
	uiData.PrimaryComponents = []RecipeComponentInfo{
		{ItemID: 1001, UniqueID: 5001, Name: "Iron Ingot", Icon: 100, Quantity: 5, QuantityUsed: 2},
		{ItemID: 1002, UniqueID: 5002, Name: "Steel Ingot", Icon: 101, Quantity: 3, QuantityUsed: 2},
	}

	// TODO: Send actual packet to client
	log.Printf("Would send recipe UI data: %+v", uiData)

	return nil
}

// SendItemCreationUI builds and sends the item creation/crafting progress UI packet.
func (pb *DefaultPacketBuilder) SendItemCreationUI(clientID uint32, recipeID uint32) error {
	log.Printf("Building WS_ShowItemCreation packet for client %d, recipe %d", clientID, recipeID)

	// TODO: Implement actual packet building
	// This would build the crafting progress window with stages

	uiData := ItemCreationUIData{
		MaxPossibleDurability: MaxDurability,
		MaxPossibleProgress:   MaxProgress,
		ProductProgressNeeded: MaxProgress,
		ProgressLevelsKnown:   0, // Player's highest known stage
	}

	// Add process stages (0-3, stage 4 is completion)
	for i := 0; i < 4; i++ {
		stage := ItemCreationStage{
			Product: ItemCreationProduct{
				Name: fmt.Sprintf("Stage %d Product", i),
				Icon: uint32(1000 + i),
			},
		}

		switch i {
		case 0:
			stage.ProgressNeeded = 0 // Stage 0 is fuel/byproduct
		case 1:
			stage.ProgressNeeded = ProgressStage1
		case 2:
			stage.ProgressNeeded = ProgressStage2
		case 3:
			stage.ProgressNeeded = ProgressStage3
		}

		uiData.ProcessStages = append(uiData.ProcessStages, stage)
	}

	// Final product (stage 4)
	uiData.ProductItem = ItemCreationProduct{
		Name: "Completed Item",
		Icon: 2000,
	}

	// TODO: Add skills for tradeskill techniques
	uiData.SkillIDs = []uint32{
		// These would be populated from player's spellbook based on recipe technique
	}

	log.Printf("Would send item creation UI data: %+v", uiData)
	return nil
}

// StopCrafting sends the stop crafting packet.
func (pb *DefaultPacketBuilder) StopCrafting(clientID uint32) error {
	log.Printf("Sending OP_StopItemCreationMsg to client %d", clientID)

	// TODO: Send actual packet
	// This would be a simple packet with opcode OP_StopItemCreationMsg and no data

	return nil
}

// CounterReaction sends the event counter reaction packet.
func (pb *DefaultPacketBuilder) CounterReaction(clientID uint32, countered bool) error {
	log.Printf("Sending WS_TSEventReaction to client %d, countered=%v", clientID, countered)

	// TODO: Build and send WS_TSEventReaction packet
	// packet->setDataByName("counter_reaction", countered ? 1 : 0);

	return nil
}

// UpdateCreateItem sends crafting progress update packet.
func (pb *DefaultPacketBuilder) UpdateCreateItem(clientID uint32, update CraftingUpdate) error {
	log.Printf("Sending WS_UpdateCreateItem to client %d: progress=%d, durability=%d, effect=%d",
		clientID, update.TotalProgress, update.TotalDurability, update.Effect)

	// Calculate progress level based on current progress
	progressLevel := int8(0)
	if update.TotalProgress >= MaxProgress {
		progressLevel = 4
	} else if update.TotalProgress >= ProgressStage3 {
		progressLevel = 3
	} else if update.TotalProgress >= ProgressStage2 {
		progressLevel = 2
	} else if update.TotalProgress >= ProgressStage1 {
		progressLevel = 1
	}
	update.ProgressLevel = progressLevel

	// TODO: Build and send actual WS_UpdateCreateItem packet
	// This would include:
	// - spawn_id (table spawn ID)
	// - effect (1=crit success, 2=success, 3=failure, 4=crit failure)
	// - total_durability
	// - total_progress
	// - durability_change
	// - progress_change
	// - progress_level
	// - reaction_icon (if event)
	// - reaction_name (if event)

	if update.Event != nil {
		log.Printf("Including event in update: %s (icon: %d)", update.Event.Name, update.Event.Icon)
	}

	return nil
}

// PacketHelper provides utility functions for packet building.
type PacketHelper struct{}

// CalculateProgressStage determines the progress stage based on current progress.
func (ph *PacketHelper) CalculateProgressStage(progress int32) int8 {
	if progress >= MaxProgress {
		return 4
	} else if progress >= ProgressStage3 {
		return 3
	} else if progress >= ProgressStage2 {
		return 2
	} else if progress >= ProgressStage1 {
		return 1
	}
	return 0
}

// GetMassProductionQuantities returns the available mass production quantities.
func (ph *PacketHelper) GetMassProductionQuantities(maxLevel int) []int32 {
	// Base quantities
	quantities := []int32{1}

	// Add additional quantities based on achievement/level
	// This matches the C++ logic: v{1,2,4,6,11,21}[mp] where mp is 5
	maxQuantities := []int32{1, 2, 4, 6, 11, 21}

	for i := 1; i < len(maxQuantities) && i <= maxLevel; i++ {
		quantities = append(quantities, maxQuantities[i]*5)
	}

	return quantities
}

// ValidateRecipeComponents checks if the player has the required components.
func (ph *PacketHelper) ValidateRecipeComponents(playerID uint32, components []ComponentUsage) error {
	// TODO: Implement component validation
	// This would check player inventory for required items and quantities

	if len(components) == 0 {
		return fmt.Errorf("no components provided")
	}

	for _, component := range components {
		if component.ItemUniqueID == 0 {
			return fmt.Errorf("invalid component unique ID")
		}
		if component.Quantity <= 0 {
			return fmt.Errorf("invalid component quantity: %d", component.Quantity)
		}
	}

	log.Printf("Component validation passed for player %d", playerID)
	return nil
}

// CalculateItemPacketType determines the packet type based on client version.
func (ph *PacketHelper) CalculateItemPacketType(clientVersion int16) int16 {
	// TODO: Implement version-specific packet type calculation
	// This would match the GetItemPacketType function from the C++ code

	if clientVersion < 860 {
		return 1 // Older packet format
	} else if clientVersion < 1193 {
		return 2 // Middle packet format
	} else {
		return 3 // Newer packet format
	}
}

// GetClientItemPacketOffset returns the item packet offset for a client version.
func (ph *PacketHelper) GetClientItemPacketOffset(clientVersion int16) int32 {
	// TODO: Implement version-specific offset calculation
	// This matches client->GetClientItemPacketOffset() from C++

	if clientVersion < 860 {
		return -1 // Use default offset
	}
	return 2 // Standard offset for newer clients
}

// ComponentSlotInfo represents information about recipe component slots.
type ComponentSlotInfo struct {
	SlotID       int8                  // Component slot (0=primary, 1-4=build, 5=fuel)
	Title        string                // Component title/name
	QuantityReq  int16                 // Required quantity
	QuantityHave int16                 // Available quantity
	Items        []RecipeComponentInfo // Available items for this slot
}

// BuildComponentSlots creates component slot information for a recipe.
func (ph *PacketHelper) BuildComponentSlots(recipeID uint32, playerID uint32) ([]ComponentSlotInfo, error) {
	// TODO: Implement actual component slot building
	// This would query the recipe and player inventory to build component options

	slots := []ComponentSlotInfo{
		{
			SlotID:       ComponentSlotPrimary,
			Title:        "Primary Component",
			QuantityReq:  2,
			QuantityHave: 5,
			Items: []RecipeComponentInfo{
				{ItemID: 1001, UniqueID: 5001, Name: "Iron Ingot", Icon: 100, Quantity: 5},
			},
		},
		{
			SlotID:       ComponentSlotFuel,
			Title:        "Fuel",
			QuantityReq:  1,
			QuantityHave: 3,
			Items: []RecipeComponentInfo{
				{ItemID: 2001, UniqueID: 6001, Name: "Coal", Icon: 200, Quantity: 3},
			},
		},
	}

	return slots, nil
}

// EffectTypeFromOutcome converts a crafting outcome to an effect type.
func (ph *PacketHelper) EffectTypeFromOutcome(outcome CraftingOutcome) int8 {
	if outcome.CriticalSuccess {
		return 1 // Critical success
	} else if outcome.Success {
		return 2 // Regular success
	} else if outcome.CriticalFailure {
		return 4 // Critical failure
	} else {
		return 3 // Regular failure
	}
}

// ClampProgress ensures progress values are within valid ranges.
func (ph *PacketHelper) ClampProgress(progress int32) int32 {
	return int32(math.Max(float64(MinProgress), math.Min(float64(MaxProgress), float64(progress))))
}

// ClampDurability ensures durability values are within valid ranges.
func (ph *PacketHelper) ClampDurability(durability int32) int32 {
	return int32(math.Max(float64(MinDurability), math.Min(float64(MaxDurability), float64(durability))))
}
