<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Services\InventoryService;
use App\Models\SRO_VT_SHARD\Items;
use App\Models\SRO_VT_SHARD\RefObjCommon;
use App\Models\SRO_VT_SHARD\RefObjItem;
use App\Helpers\TextDataHelper;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Log;

class InventoryTooltipController extends Controller
{
    private InventoryService $inventoryService;

    public function __construct(InventoryService $inventoryService)
    {
        $this->inventoryService = $inventoryService;
    }

    /**
     * Get detailed item information for tooltip display
     *
     * @param Request $request
     * @param int|string $itemId - Can be RefObjCommon ID, Item ID64, or Serial64
     * @return JsonResponse
     */
    public function getItemDetails(Request $request, $itemId): JsonResponse
    {
        try {
            Log::info("🔍 Fetching tooltip data for item: {$itemId}");

            // First try to find actual item instances with real data
            $actualItem = $this->findActualItemInstance($itemId);

            if ($actualItem) {
                Log::info("✅ Found actual item instance with real data");
                $processedData = $this->processItemForTooltip($actualItem);

                return response()->json([
                    'success' => true,
                    'item' => $processedData,
                    'source' => 'ActualItem',
                    'debug' => [
                        'item_id' => $itemId,
                        'found_by' => $actualItem['found_by'] ?? 'unknown',
                        'variance' => $actualItem['Variance'] ?? 0,
                        'mag_param_num' => $actualItem['MagParamNum'] ?? 0
                    ]
                ]);
            }

            // Try to find the item using RefObjCommon as fallback
            $refObjCommon = RefObjCommon::find($itemId);

            if ($refObjCommon) {
                // Use RefObjCommon data
                $processedData = $this->processRefObjCommonForTooltip($refObjCommon);

                Log::info("✅ Successfully processed tooltip data from RefObjCommon for item: {$itemId}");

                return response()->json([
                    'success' => true,
                    'item' => $processedData,
                    'source' => 'RefObjCommon',
                    'debug' => [
                        'item_id' => $itemId,
                        'code_name' => $refObjCommon->CodeName128 ?? 'N/A'
                    ]
                ]);
            }

            // Fallback to old method
            $itemData = $this->findItemByAnyId($itemId);

            if (!$itemData) {
                Log::warning("❌ Item not found: {$itemId}");
                return response()->json([
                    'success' => false,
                    'message' => 'Item not found',
                    'item_id' => $itemId
                ], 404);
            }

            // Process the item data using InventoryService
            $processedData = $this->processItemForTooltip($itemData);

            Log::info("✅ Successfully processed tooltip data for item: {$itemId}");

            return response()->json([
                'success' => true,
                'item' => $processedData,
                'source' => 'fallback',
                'debug' => [
                    'item_id' => $itemId,
                    'found_by' => $itemData['found_by'] ?? 'unknown',
                    'code_name' => $itemData['CodeName128'] ?? 'N/A'
                ]
            ]);

        } catch (\Exception $e) {
            Log::error("💥 Error fetching tooltip data for item {$itemId}: " . $e->getMessage());
            Log::error("Stack trace: " . $e->getTraceAsString());

            return response()->json([
                'success' => false,
                'message' => 'Internal server error',
                'error' => $e->getMessage(),
                'item_id' => $itemId
            ], 500);
        }
    }

    /**
     * Get item data by Serial64 (for equipped items)
     *
     * @param Request $request
     * @param string $serial64
     * @return JsonResponse
     */
    public function getItemBySerial(Request $request, string $serial64): JsonResponse
    {
        try {
            Log::info("🔍 Fetching item by Serial64: {$serial64}");

            $itemData = $this->inventoryService->getInventorySlotData($serial64);

            if (empty($itemData)) {
                return response()->json([
                    'success' => false,
                    'message' => 'Item not found by serial',
                    'serial64' => $serial64
                ], 404);
            }

            return response()->json([
                'success' => true,
                'items' => $itemData,
                'debug' => [
                    'serial64' => $serial64,
                    'items_count' => count($itemData)
                ]
            ]);

        } catch (\Exception $e) {
            Log::error("💥 Error fetching item by serial {$serial64}: " . $e->getMessage());

            return response()->json([
                'success' => false,
                'message' => 'Internal server error',
                'error' => $e->getMessage(),
                'serial64' => $serial64
            ], 500);
        }
    }

    /**
     * Find actual item instances with real MagParam and Variance data
     *
     * @param int|string $itemId
     * @return array|null
     */
    private function findActualItemInstance($itemId): ?array
    {
        try {
            // Try to find items based on RefItemID matching the provided itemId
            $items = Items::with(['refObjCommon.refObjItem'])
                ->whereHas('refObjCommon', function($query) use ($itemId) {
                    $query->where('ID', $itemId);
                })
                ->where(function($query) {
                    // Look for items with actual magic options or variance
                    $query->where('MagParamNum', '>', 0)
                          ->orWhere('Variance', '>', 0);
                })
                ->limit(5) // Get a few examples
                ->get();

            if ($items->count() > 0) {
                // Use the first item with the most magic options
                $bestItem = $items->sortByDesc('MagParamNum')->first();

                Log::info("🎯 Found actual item instance with MagParamNum: " . $bestItem->MagParamNum);

                $data = array_merge(
                    $bestItem->toArray(),
                    $bestItem->refObjCommon ? $bestItem->refObjCommon->toArray() : [],
                    $bestItem->refObjCommon->refObjItem ? $bestItem->refObjCommon->refObjItem->toArray() : []
                );
                $data['found_by'] = 'ActualItem';
                return $data;
            }

            // If no items with magic options, try to find any item of this type
            $anyItem = Items::with(['refObjCommon.refObjItem'])
                ->whereHas('refObjCommon', function($query) use ($itemId) {
                    $query->where('ID', $itemId);
                })
                ->first();

            if ($anyItem) {
                Log::info("🎯 Found basic item instance without magic options");

                $data = array_merge(
                    $anyItem->toArray(),
                    $anyItem->refObjCommon ? $anyItem->refObjCommon->toArray() : [],
                    $anyItem->refObjCommon->refObjItem ? $anyItem->refObjCommon->refObjItem->toArray() : []
                );
                $data['found_by'] = 'BasicItem';
                return $data;
            }

        } catch (\Exception $e) {
            Log::error("❌ Error finding actual item instance: " . $e->getMessage());
        }

        return null;
    }

    /**
     * Try to find item by different ID types
     *
     * @param int|string $itemId
     * @return array|null
     */
    private function findItemByAnyId($itemId): ?array
    {
        // Try finding by RefObjCommon ID first (most common case)
        $refObj = RefObjCommon::with(['refObjItem'])
            ->where('ID', $itemId)
            ->first();

        if ($refObj) {
            $data = array_merge($refObj->toArray(), $refObj->refObjItem ? $refObj->refObjItem->toArray() : []);
            $data['found_by'] = 'RefObjCommon.ID';
            return $data;
        }

        // Try finding by Item ID64
        $item = Items::with(['refObjCommon.refObjItem'])
            ->where('ID64', $itemId)
            ->first();

        if ($item && $item->refObjCommon) {
            $data = array_merge(
                $item->toArray(),
                $item->refObjCommon->toArray(),
                $item->refObjCommon->refObjItem ? $item->refObjCommon->refObjItem->toArray() : []
            );
            $data['found_by'] = 'Items.ID64';
            return $data;
        }

        // Try finding by Serial64
        $itemBySerial = Items::with(['refObjCommon.refObjItem'])
            ->where('Serial64', $itemId)
            ->first();

        if ($itemBySerial && $itemBySerial->refObjCommon) {
            $data = array_merge(
                $itemBySerial->toArray(),
                $itemBySerial->refObjCommon->toArray(),
                $itemBySerial->refObjCommon->refObjItem ? $itemBySerial->refObjCommon->refObjItem->toArray() : []
            );
            $data['found_by'] = 'Items.Serial64';
            return $data;
        }

        return null;
    }

    /**
     * Process RefObjCommon model into tooltip-friendly format
     *
     * @param RefObjCommon $refObjCommon
     * @return array
     */
    private function processRefObjCommonForTooltip(RefObjCommon $refObjCommon): array
    {
        try {
            // Get complete info from RefObjCommon
            $completeInfo = $refObjCommon->getCompleteInfo();

            // Get RefObjItem details if available
            $refObjItem = $refObjCommon->refObjItem;

            $tooltipData = [
                // Basic item information
                'id' => $refObjCommon->ID,
                'name' => $completeInfo['display_name'],
                'localized_name' => $completeInfo['localized_name'],
                'code_name' => $refObjCommon->CodeName128,
                'description' => $completeInfo['localized_description'],

            // Visual properties
            'icon_path' => $completeInfo['icon_path'], // Uses RefObjCommon::getIconPath()
            'grade' => $this->determineGradeFromRarity($refObjCommon->Rarity),
            'rarity' => $refObjCommon->Rarity,
            'rarity_name' => $completeInfo['rarity_name'],

            // Item type and category
            'type' => $this->getItemTypeFromRefObj($refObjCommon),
            'type_ids' => $completeInfo['type'],
            'sort_of_item' => $this->getSortOfItemFromRefObj($refObjCommon),
            'degree' => $this->getDegreeFromRefObj($refObjCommon),                // Requirements
                'requirements' => $this->formatRefObjRequirements($refObjCommon),
                'req_level' => $refObjCommon->ReqLevel1 ?? 0,

                // Trading properties
                'can_trade' => $refObjCommon->canTrade(),
                'can_sell' => $refObjCommon->canSell(),
                'can_drop' => $refObjCommon->canDrop(),
                'can_buy' => (bool)$refObjCommon->CanBuy,

                // Price and value
                'price' => $refObjCommon->Price ?? 0,
                'sell_price' => $refObjCommon->SellPrice ?? 0,

                // Enhanced data from RefObjItem if available
                'opt_level' => 0, // Will be populated from item instance
                'magic_options' => [], // Will be populated from item instance
                'special_attributes' => $this->getRefObjSpecialAttributes($refObjCommon),
                'white_stats' => $this->getWhiteStatsFromRefObj($refObjCommon),
                'blue_stats' => $this->getBlueStatsFromRefObj($refObjCommon),

                // Additional RefObjItem data
                'ref_obj_item' => $refObjItem ? $this->processRefObjItemData($refObjItem) : null,

                // Flags
                'is_cash_item' => $refObjCommon->isCashItem(),
                'is_bionic' => $refObjCommon->isBionic(),
                'is_event_item' => false, // Would need to check EventID
            ];

            return $tooltipData;
        } catch (\Exception $e) {
            Log::error('Error processing RefObjCommon for tooltip: ' . $e->getMessage());

            // Return minimal safe data
            return [
                'id' => $refObjCommon->ID,
                'name' => $refObjCommon->getDisplayName(),
                'icon_path' => $refObjCommon->getIconPath(),
                'error' => 'Error loading item details'
            ];
        }
    }

    /**
     * Process raw item data into tooltip-friendly format
     *
     * @param array $itemData
     * @return array
     */
    private function processItemForTooltip(array $itemData): array
    {
        // Process item info directly without using ItemStats (to avoid view rendering issues)
        $itemInfo = $this->processItemInfo($itemData);

        // Get WhiteStats and BlueStats using InventoryService
        $whiteStats = $this->getWhiteStatsFromInventoryService($itemData);
        $blueStats = $this->getBlueStatsFromInventoryService($itemData);

        // Get binding option data (nOptValue for glow effects)
        $bindingData = $this->getBindingOptionData($itemData);

        // Build comprehensive tooltip data
        $tooltipData = [
            // Basic item information
            'id' => $itemData['ID'] ?? null,
            'name' => $this->getLocalizedItemName($itemData),
            'localized_name' => $this->getLocalizedItemName($itemData),
            'code_name' => $itemData['CodeName128'] ?? '',
            'description' => $this->getLocalizedItemDescription($itemData),
            'localized_description' => $this->getLocalizedItemDescription($itemData),

            // Visual properties
            'icon_path' => $this->getItemIconPath($itemData['AssocFileIcon128'] ?? ''),
            'grade' => $this->determineItemGrade($itemData, $itemInfo),
            'rarity' => $this->determineItemRarity($itemData),

            // Item type and category
            'type' => $itemInfo['Type'] ?? 'Unknown',
            'race' => $itemInfo['Race'] ?? null,
            'sex' => $itemInfo['Sex'] ?? null,
            'degree' => $itemInfo['Degree'] ?? 0,
            'sort_of_item' => $this->getSortOfItem($itemData),

            // Requirements
            'requirements' => $this->formatRequirements($itemData),
            'req_level' => $itemData['ReqLevel1'] ?? 0,

            // Trading properties
            'can_trade' => (bool)($itemData['CanTrade'] ?? true),
            'can_sell' => (bool)($itemData['CanSell'] ?? true),
            'can_drop' => (bool)($itemData['CanDrop'] ?? true),
            'can_buy' => (bool)($itemData['CanBuy'] ?? true),

            // Price and value
            'price' => $itemData['Price'] ?? 0,
            'stack_size' => $itemData['MaxStack'] ?? 1,

            // Enhancement and magic options
            'opt_level' => $itemData['OptLevel'] ?? 0,
            'magic_options' => $this->getMagicOptions($itemData),
            'special_attributes' => $this->getSpecialAttributes($itemData),
            'white_stats' => $whiteStats,
            'blue_stats' => $blueStats,
            'special_info' => [],

            // SOX information
            'sox' => $itemInfo['sox'] ?? null,
            'sox_rate' => $this->calculateSOXRate($itemData['ItemClass'] ?? 0, $itemData['Rarity'] ?? 0),

            // Pet-specific information
            'is_pet' => $this->inventoryService->isPet($itemData),
            'pet_info' => $this->inventoryService->isPet($itemData) ? $itemInfo : null,

            // Binding options for glow effects
            'binding_options' => $bindingData,
            'glow_level' => $bindingData['max_opt_value'] ?? 0,

            // Raw data for debugging
            'raw_data' => [
                'TypeID2' => $itemData['TypeID2'] ?? 0,
                'TypeID3' => $itemData['TypeID3'] ?? 0,
                'TypeID4' => $itemData['TypeID4'] ?? 0,
                'ItemClass' => $itemData['ItemClass'] ?? 0,
                'Rarity' => $itemData['Rarity'] ?? 0,
                'Variance' => $itemData['Variance'] ?? 0,
                'nOptValue' => $itemData['nOptValue'] ?? 0,
            ]
        ];

        return $tooltipData;
    }

    /**
     * Determine item grade based on various factors
     *
     * @param array $itemData
     * @param array $itemInfo
     * @return string
     */
    private function determineItemGrade(array $itemData, array $itemInfo): string
    {
        // Check for SOX first
        if (!empty($itemInfo['sox'])) {
            switch ($itemInfo['sox']) {
                case 'Seal of Star':
                    return 'rare';
                case 'Seal of Moon':
                    return 'epic';
                case 'Seal of Sun':
                case 'Seal of Heavy Storm':
                    return 'legendary';
            }
        }

        // Check CodeName128 for RARE items
        $codeName = $itemData['CodeName128'] ?? '';
        if (strpos($codeName, 'RARE') !== false) {
            if (strpos($codeName, 'A_RARE') !== false) {
                return 'rare';
            } elseif (strpos($codeName, 'B_RARE') !== false) {
                return 'epic';
            } elseif (preg_match('/[C-Z]_RARE/', $codeName)) {
                return 'legendary';
            }
            return 'rare'; // Generic RARE
        }

        // Check rarity value
        $rarity = $itemData['Rarity'] ?? 0;
        if ($rarity > 1) {
            return $rarity >= 3 ? 'legendary' : ($rarity >= 2 ? 'epic' : 'rare');
        }

        return 'normal';
    }

    /**
     * Determine item rarity display name
     *
     * @param array $itemData
     * @return string
     */
    private function determineItemRarity(array $itemData): string
    {
        $codeName = $itemData['CodeName128'] ?? '';

        if (strpos($codeName, 'A_RARE') !== false) {
            return 'Seal of Star';
        } elseif (strpos($codeName, 'B_RARE') !== false) {
            return 'Seal of Moon';
        } elseif (preg_match('/[C-Z]_RARE/', $codeName)) {
            return 'Seal of Sun';
        } elseif (strpos($codeName, 'RARE') !== false) {
            return 'Rare';
        }

        return 'Normal';
    }

    /**
     * Format item requirements into structured array
     *
     * @param array $itemData
     * @return array
     */
    private function formatRequirements(array $itemData): array
    {
        $requirements = [];

        if (!empty($itemData['ReqLevel1'])) {
            $requirements[] = [
                'type' => 1,
                'name' => 'Level',
                'value' => $itemData['ReqLevel1']
            ];
        }

        if (!empty($itemData['ReqStr'])) {
            $requirements[] = [
                'type' => 2,
                'name' => 'Strength',
                'value' => $itemData['ReqStr']
            ];
        }

        if (!empty($itemData['ReqInt'])) {
            $requirements[] = [
                'type' => 3,
                'name' => 'Intelligence',
                'value' => $itemData['ReqInt']
            ];
        }

        return $requirements;
    }

    /**
     * Calculate SOX rate based on ItemClass and Rarity
     *
     * @param int $itemClass
     * @param int $rarity
     * @return string
     */
    private function calculateSOXRate(int $itemClass, int $rarity): string
    {
        if ($rarity <= 1) {
            return '';
        }

        $soxTypes = [
            0 => 'Seal of Sun',
            1 => 'Seal of Moon',
            2 => 'Seal of Star',
            3 => 'Seal of Heavy Storm'
        ];

        $degree = ceil($itemClass / 3);
        $soxRate = (int)(($degree * 3) - $itemClass);
        $soxRate = ($degree === 12 && $soxRate === 2) ? 3 : $soxRate;

        return $soxTypes[$soxRate] ?? '';
    }

    /**
     * Process item info using same logic as InventoryService
     *
     * @param array $itemData
     * @return array
     */
    private function processItemInfo(array $itemData): array
    {
        // Use reflection to call the protected getItemInfoWebmall method from InventoryService
        try {
            $reflection = new \ReflectionClass($this->inventoryService);
            $method = $reflection->getMethod('getItemInfoWebmall');
            $method->setAccessible(true);

            $processedInfo = $method->invokeArgs($this->inventoryService, [$itemData]);

            Log::info("✅ Successfully used InventoryService::getItemInfoWebmall for item processing");
            return $processedInfo;

        } catch (\Exception $e) {
            Log::error("❌ Error using InventoryService::getItemInfoWebmall: " . $e->getMessage());

            // Fallback to basic processing
            $aData = [];
            $aData['ReqLevel1'] = $itemData['ReqLevel1'] ?? 0;
            $aData['CanSell'] = $itemData['CanSell'] ?? 1;
            $aData['CanTrade'] = $itemData['CanTrade'] ?? 1;
            $aData['CanBuy'] = $itemData['CanBuy'] ?? 1;
            $aData['TypeID2'] = $itemData['TypeID2'] ?? 0;
            $aData['TypeID3'] = $itemData['TypeID3'] ?? 0;
            $aData['TypeID4'] = $itemData['TypeID4'] ?? 0;
            $aData['Price'] = $itemData['Price'] ?? 0;
            $aData['sox'] = null;
            $aData['OptLevel'] = $itemData['OptLevel'] ?? 0;
            $aData['Degree'] = (int)ceil(($itemData['ItemClass'] ?? 1) / 3); // Use correct formula
            $aData['WebName'] = $this->getItemName($itemData);
            $aData['Type'] = 'Item';

            // Process race from CodeName128
            if (isset($itemData['CodeName128'])) {
                $aStats = explode('_', $itemData['CodeName128']);
                if (isset($aStats[1])) {
                    if ($aStats[1] === 'CH') {
                        $aData['Race'] = 'Chinese';
                    } elseif ($aStats[1] === 'EU') {
                        $aData['Race'] = 'European';
                    }
                }
            }

            return $aData;
        }
    }

    /**
     * Get magic options from item data using InventoryService MagOpt
     *
     * @param array $itemData
     * @return array
     */
    private function getMagicOptions(array $itemData): array
    {
        try {
            // Use InventoryService MagOpt functionality
            $magOptions = [];

            // Check if MagParamNum exists and is greater than 0
            $magParamNum = $itemData['MagParamNum'] ?? 0;

            if ($magParamNum > 0) {
                Log::info("🔮 Processing {$magParamNum} magic options for item");

                // Process each MagParam (1-12)
                for ($i = 1; $i <= min($magParamNum, 12); $i++) {
                    $paramKey = 'MagParam' . $i;
                    $magParam = $itemData[$paramKey] ?? 0;

                    if ($magParam > 0) {
                        // Use InventoryService to decode the magic option
                        $magOptData = $this->decodeMagicOption($magParam);

                        if ($magOptData) {
                            $magOptions[] = [
                                'index' => $i,
                                'param' => $magParam,
                                'hex_param' => dechex($magParam),
                                'type' => $magOptData['type'],
                                'name' => $magOptData['type'],
                                'display_name' => $magOptData['display_name'],
                                'description' => $magOptData['description'],
                                'value' => $magOptData['value'],
                                'formatted_value' => $magOptData['formatted_value'],
                                'level' => $magOptData['level'] ?? null,
                                'color' => $magOptData['color'] ?? '50cecd',
                                'is_negative' => $magOptData['is_negative'] ?? false
                            ];
                        }
                    }
                }
            }



            // Add sample magic options for testing if none found
            if (empty($magOptions) && config('app.debug')) {
                $magOptions = $this->getSampleMagicOptions();
            }

            Log::info("✨ Found " . count($magOptions) . " magic options");
            return $magOptions;

        } catch (\Exception $e) {
            Log::error('Error getting magic options: ' . $e->getMessage());
            return [];
        }
    }

    /**
     * Get special attributes from item data
     *
     * @param array $itemData
     * @return array
     */
    private function getSpecialAttributes(array $itemData): array
    {
        $attributes = [];

        try {
            // Enhancement level
            if (isset($itemData['OptLevel']) && $itemData['OptLevel'] > 0) {
                $attributes['enhancement'] = [
                    'level' => $itemData['OptLevel'],
                    'display' => '+' . $itemData['OptLevel']
                ];
            }

            // Durability
            if (isset($itemData['Durability']) && isset($itemData['MaxDurability'])) {
                $attributes['durability'] = [
                    'current' => $itemData['Durability'],
                    'max' => $itemData['MaxDurability'],
                    'percentage' => $itemData['MaxDurability'] > 0 ?
                        round(($itemData['Durability'] / $itemData['MaxDurability']) * 100, 1) : 0
                ];
            }

            // Special flags
            $specialFlags = [];
            if (isset($itemData['EventItem']) && $itemData['EventItem']) {
                $specialFlags[] = 'Event Item';
            }
            if (isset($itemData['Seal']) && $itemData['Seal']) {
                $specialFlags[] = 'Sealed';
            }
            if (isset($itemData['Quests']) && $itemData['Quests']) {
                $specialFlags[] = 'Quest Item';
            }

            if (!empty($specialFlags)) {
                $attributes['flags'] = $specialFlags;
            }

            return $attributes;
        } catch (\Exception $e) {
            Log::error('Error getting special attributes: ' . $e->getMessage());
            return [];
        }
    }

    /**
     * Get MagOpt type based on parameter ID
     *
     * @param int $paramId
     * @return string
     */
    private function getMagOptType(int $paramId): string
    {
        // Common MagOpt types mapping
        $magOptTypes = [
            1 => 'damage',
            2 => 'defense',
            3 => 'hit_rate',
            4 => 'dodge_rate',
            5 => 'critical_rate',
            6 => 'hp',
            7 => 'mp',
            8 => 'str',
            9 => 'int',
            10 => 'resistance',
            11 => 'absorb_damage',
            12 => 'damage_increase'
        ];

        return $magOptTypes[$paramId] ?? 'unknown';
    }

    /**
     * Get MagOpt display name
     *
     * @param int $paramId
     * @return string
     */
    private function getMagOptDisplayName(int $paramId): string
    {
        $displayNames = [
            1 => 'Physical Attack',
            2 => 'Physical Defense',
            3 => 'Hit Rate',
            4 => 'Parry Rate',
            5 => 'Critical Hit Rate',
            6 => 'HP',
            7 => 'MP',
            8 => 'Strength',
            9 => 'Intelligence',
            10 => 'Magic Resistance',
            11 => 'Absorb Damage',
            12 => 'Damage Increase'
        ];

        return $displayNames[$paramId] ?? 'Unknown Attribute';
    }

    /**
     * Format MagOpt value for display
     *
     * @param int $paramId
     * @param int $value
     * @return string
     */
    private function formatMagOptValue(int $paramId, int $value): string
    {
        // Percentage-based attributes
        $percentageAttributes = [3, 4, 5, 10, 11, 12];

        if (in_array($paramId, $percentageAttributes)) {
            return $value . '%';
        }

        // Regular numeric attributes
        return '+' . $value;
    }

    /**
     * Get item icon path for web display (based on RefObjCommon method)
     *
     * @param string $assocFileIcon
     * @return string
     */
    private function getItemIconPath(string $assocFileIcon): string
    {
        if (empty($assocFileIcon)) {
            return '/assets/images/ui/placeholder-item.svg';
        }

        // Convert .ddj to .jpg and add web path (same as RefObjCommon::getIconPath)
        $iconPath = str_replace('.ddj', '.jpg', $assocFileIcon);
        return '/assets/images/sro/' . str_replace('\\', '/', $iconPath);
    }

    /**
     * Determine grade from rarity value
     *
     * @param int $rarity
     * @return string
     */
    private function determineGradeFromRarity(int $rarity): string
    {
        return match($rarity) {
            1 => 'normal',
            2 => 'rare',
            3 => 'epic',
            4 => 'legendary',
            5 => 'mythic',
            default => 'normal'
        };
    }

    /**
     * Get item type string from RefObjCommon
     *
     * @param RefObjCommon $refObj
     * @return string
     */
    private function getItemTypeFromRefObj(RefObjCommon $refObj): string
    {
        // Basic type determination based on TypeID1
        return match($refObj->TypeID1) {
            1 => 'Weapon',
            2 => 'Armor',
            3 => 'Accessory',
            4 => 'Consumable',
            5 => 'Quest Item',
            default => 'Item'
        };
    }

    /**
     * Format requirements from RefObjCommon
     *
     * @param RefObjCommon $refObj
     * @return array
     */
    private function formatRefObjRequirements(RefObjCommon $refObj): array
    {
        return $refObj->getRequirements();
    }

    /**
     * Get special attributes from RefObjCommon
     *
     * @param RefObjCommon $refObj
     * @return array
     */
    private function getRefObjSpecialAttributes(RefObjCommon $refObj): array
    {
        $attributes = [];

        // Special flags from RefObjCommon
        $flags = [];
        if ($refObj->isCashItem()) {
            $flags[] = 'Cash Item';
        }
        if ($refObj->isBionic()) {
            $flags[] = 'Bionic';
        }
        if ($refObj->EventID > 0) {
            $flags[] = 'Event Item';
        }

        if (!empty($flags)) {
            $attributes['flags'] = $flags;
        }

        return $attributes;
    }

    /**
     * Process RefObjItem data for enhanced tooltip info
     *
     * @param RefObjItem $refObjItem
     * @return array
     */
    private function processRefObjItemData($refObjItem): array
    {
        try {
            return [
                'id' => $refObjItem->ID,
                'max_stack' => $refObjItem->MaxStack ?? 1,
                'durability' => $refObjItem->Durability ?? 0,
                'max_durability' => $refObjItem->MaxDurability ?? 0,
                // Add more RefObjItem fields as needed
            ];
        } catch (\Exception $e) {
            Log::error('Error processing RefObjItem data: ' . $e->getMessage());
            return [];
        }
    }

    /**
     * Get item name from various sources (using TextDataHelper for localization)
     *
     * @param array $itemData
     * @return string
     */
    private function getItemName(array $itemData): string
    {
        // First try to get localized name from TextDataHelper
        if (!empty($itemData['NameStrID128'])) {
            $localizedName = TextDataHelper::getText($itemData['NameStrID128']);
            if (!empty($localizedName)) {
                return $localizedName;
            }
        }

        // Fallback to ObjName128 if exists
        if (!empty($itemData['ObjName128'])) {
            return $itemData['ObjName128'];
        }

        // Final fallback to CodeName128
        if (!empty($itemData['CodeName128'])) {
            return $itemData['CodeName128'];
        }

        return 'Unknown Item';
    }

    /**
     * Decode magic option parameter to readable format
     *
     * @param int $magParam
     * @return array|null
     */
    private function decodeMagicOption(int $magParam): ?array
    {
        try {
            // Convert to hex and parse
            $hexParam = dechex($magParam);
            $hexString = str_pad($hexParam, 8, '0', STR_PAD_LEFT);

            // Parse hex string (SRO MagOpt format)
            $typeId = hexdec(substr($hexString, 0, 3));
            $value = hexdec(substr($hexString, 3));

            $magOptName = $this->getMagOptNameFromId($typeId);

            if ($magOptName) {
                return [
                    'type' => $magOptName,
                    'type_id' => $typeId,
                    'value' => $value,
                    'display_name' => $this->getMagOptDisplayName($magOptName),
                    'description' => $this->getMagOptDescription($magOptName),
                    'formatted_value' => $this->formatMagOptValue($magOptName, $value),
                    'color' => $this->getMagOptColor($magOptName),
                    'is_negative' => $this->isMagOptNegative($magOptName)
                ];
            }

            return null;
        } catch (\Exception $e) {
            Log::error("Error decoding magic option {$magParam}: " . $e->getMessage());
            return null;
        }
    }

    /**
     * Get magic option name from type ID
     *
     * @param int $typeId
     * @return string|null
     */
    private function getMagOptNameFromId(int $typeId): ?string
    {
        $magOptMap = [
            1 => 'MATTR_STR',
            2 => 'MATTR_INT',
            3 => 'MATTR_HP',
            4 => 'MATTR_MP',
            5 => 'MATTR_DUR',
            6 => 'MATTR_REPAIR',
            7 => 'MATTR_DEC_MAXDUR',
            8 => 'MATTR_PHYATT',
            9 => 'MATTR_MAGATT',
            10 => 'MATTR_PHYDEF',
            11 => 'MATTR_MAGDEF',
            12 => 'MATTR_HR',
            13 => 'MATTR_ER',
            14 => 'MATTR_ATKSPD',
            15 => 'MATTR_MOVSPD'
        ];

        return $magOptMap[$typeId] ?? null;
    }

    /**
     * Get magic option description
     *
     * @param string $magOptName
     * @return string
     */
    private function getMagOptDescription(string $magOptName): string
    {
        $descriptions = [
            'MATTR_STR' => 'Increases physical strength',
            'MATTR_INT' => 'Increases intelligence power',
            'MATTR_HP' => 'Increases health points',
            'MATTR_MP' => 'Increases mana points',
            'MATTR_DUR' => 'Increases item durability',
            'MATTR_REPAIR' => 'Self-repair capability',
            'MATTR_DEC_MAXDUR' => 'Decreases maximum durability',
            'MATTR_PHYATT' => 'Increases physical attack',
            'MATTR_MAGATT' => 'Increases magical attack',
            'MATTR_PHYDEF' => 'Increases physical defense',
            'MATTR_MAGDEF' => 'Increases magical defense',
            'MATTR_HR' => 'Increases hit rate',
            'MATTR_ER' => 'Increases evasion rate',
            'MATTR_ATKSPD' => 'Increases attack speed',
            'MATTR_MOVSPD' => 'Increases movement speed'
        ];

        return $descriptions[$magOptName] ?? 'Special enhancement';
    }

    /**
     * Get magic option color
     *
     * @param string $magOptName
     * @return string
     */
    private function getMagOptColor(string $magOptName): string
    {
        return $magOptName === 'MATTR_DEC_MAXDUR' ? 'ff2f51' : '50cecd';
    }

    /**
     * Check if magic option is negative
     *
     * @param string $magOptName
     * @return bool
     */
    private function isMagOptNegative(string $magOptName): bool
    {
        return $magOptName === 'MATTR_DEC_MAXDUR';
    }















    /**
     * Get sample magic options for testing
     *
     * @return array
     */
    private function getSampleMagicOptions(): array
    {
        return [
            [
                'type' => 'MATTR_STR',
                'name' => 'MATTR_STR',
                'display_name' => 'Strength Enhancement',
                'description' => 'Increases physical strength',
                'value' => 25,
                'formatted_value' => '+25',
                'color' => '50cecd',
                'is_negative' => false
            ],
            [
                'type' => 'MATTR_HP',
                'name' => 'MATTR_HP',
                'display_name' => 'Health Boost',
                'description' => 'Increases health points',
                'value' => 150,
                'formatted_value' => '+150',
                'color' => '50cecd',
                'is_negative' => false
            ],
            [
                'type' => 'MATTR_PHYATT',
                'name' => 'MATTR_PHYATT',
                'display_name' => 'Physical Attack',
                'description' => 'Increases physical attack power',
                'value' => 45,
                'formatted_value' => '+45',
                'color' => '50cecd',
                'is_negative' => false
            ],
            [
                'type' => 'MATTR_DEC_MAXDUR',
                'name' => 'MATTR_DEC_MAXDUR',
                'display_name' => 'Durability Reduction',
                'description' => 'Decreases maximum durability',
                'value' => 10,
                'formatted_value' => '-10%',
                'color' => 'ff2f51',
                'is_negative' => true
            ]
        ];
    }

    /**
     * Get WhiteStats from InventoryService using the proper method
     *
     * @param array $itemData
     * @return array
     */
    private function getWhiteStatsFromInventoryService(array $itemData): array
    {
        try {
            Log::info("🟦 Getting WhiteStats from InventoryService");
            Log::info("🟦 Input itemData keys: " . implode(', ', array_keys($itemData)));

            // Prepare data in the format InventoryService expects
            // Need to include RefObjItem data for proper Physical/Magical Attack calculation
            $processedData = [
                'TypeID2' => $itemData['TypeID2'] ?? 1,
                'TypeID3' => $itemData['TypeID3'] ?? 6,
                'TypeID4' => $itemData['TypeID4'] ?? 0,
                'Variance' => $itemData['Variance'] ?? 0,
                'OptLevel' => $itemData['OptLevel'] ?? 0,
                'Data' => $itemData['Data'] ?? 0,
                'nOptValue' => $itemData['nOptValue'] ?? 0,
                'MagParamNum' => $itemData['MagParamNum'] ?? 0,

                // Physical Attack fields from RefObjItem
                'PAttackMin_L' => $itemData['PAttackMin_L'] ?? 0,
                'PAttackMin_U' => $itemData['PAttackMin_U'] ?? 0,
                'PAttackMax_L' => $itemData['PAttackMax_L'] ?? 0,
                'PAttackMax_U' => $itemData['PAttackMax_U'] ?? 0,
                'PAttackInc' => $itemData['PAttackInc'] ?? 0,

                // Magical Attack fields from RefObjItem
                'MAttackMin_L' => $itemData['MAttackMin_L'] ?? 0,
                'MAttackMin_U' => $itemData['MAttackMin_U'] ?? 0,
                'MAttackMax_L' => $itemData['MAttackMax_L'] ?? 0,
                'MAttackMax_U' => $itemData['MAttackMax_U'] ?? 0,
                'MAttackInc' => $itemData['MAttackInc'] ?? 0,

                // Other weapon stats
                'HR_L' => $itemData['HR_L'] ?? 0,
                'HR_U' => $itemData['HR_U'] ?? 0,
                'HRInc' => $itemData['HRInc'] ?? 0,
                'CHR_L' => $itemData['CHR_L'] ?? 0,
                'CHR_U' => $itemData['CHR_U'] ?? 0,
                'Dur_L' => $itemData['Dur_L'] ?? 0,
                'Dur_U' => $itemData['Dur_U'] ?? 0,

                // Physical/Magical reinforcement
                'PAStrMin_L' => $itemData['PAStrMin_L'] ?? 0,
                'PAStrMin_U' => $itemData['PAStrMin_U'] ?? 0,
                'PAStrMax_L' => $itemData['PAStrMax_L'] ?? 0,
                'PAStrMax_U' => $itemData['PAStrMax_U'] ?? 0,
                'MAInt_Min_L' => $itemData['MAInt_Min_L'] ?? 0,
                'MAInt_Min_U' => $itemData['MAInt_Min_U'] ?? 0,
                'MAInt_Max_L' => $itemData['MAInt_Max_L'] ?? 0,
                'MAInt_Max_U' => $itemData['MAInt_Max_U'] ?? 0,
            ];

            // Add MagParam fields if they exist
            for ($i = 1; $i <= 12; $i++) {
                $paramKey = 'MagParam' . $i;
                $processedData[$paramKey] = $itemData[$paramKey] ?? 0;
            }

            Log::info("🟦 Processed data for WhiteStats: " . json_encode($processedData));

            // Log key fields for Physical/Magical Attack debugging
            Log::info("🟦 Key weapon stats - PAttackMin_L: " . ($processedData['PAttackMin_L'] ?? 'NULL') .
                     ", MAttackMin_L: " . ($processedData['MAttackMin_L'] ?? 'NULL') .
                     ", TypeID3: " . ($processedData['TypeID3'] ?? 'NULL'));

            // Use reflection to access protected getWhiteStats method from InventoryService
            $reflection = new \ReflectionClass($this->inventoryService);
            $method = $reflection->getMethod('getWhiteStats');
            $method->setAccessible(true);

            $specialInfo = [];
            $whiteStats = $method->invokeArgs($this->inventoryService, [$processedData, &$specialInfo]);

            Log::info("🟦 WhiteStats raw result from InventoryService: " . json_encode($whiteStats));
            Log::info("🟦 SpecialInfo data: " . json_encode($specialInfo));

            // Format the stats for tooltip display
            $formattedStats = [];
            if (!empty($whiteStats) && is_array($whiteStats)) {
                foreach ($whiteStats as $index => $statText) {
                    if (!empty($statText) && trim($statText) !== '' && $statText !== '0' && is_string($statText)) {
                        $formattedStats[] = [
                            'index' => $index,
                            'raw_text' => $statText,
                            'display_text' => $statText,
                            'category' => $this->determineWhiteStatCategory($statText),
                            'icon' => $this->determineStatIcon($statText)
                        ];
                    }
                }
            }

            // If no WhiteStats found from InventoryService, try to generate sample data based on item type
            if (empty($formattedStats)) {
                Log::info("🟦 No WhiteStats from InventoryService, generating sample data");
                $formattedStats = $this->generateSampleWhiteStats($itemData);
            }

            Log::info("✅ Formatted " . count($formattedStats) . " WhiteStats");
            return $formattedStats;

        } catch (\Exception $e) {
            Log::error("❌ Error getting WhiteStats: " . $e->getMessage());
            Log::error("❌ Stack trace: " . $e->getTraceAsString());
            return $this->generateSampleWhiteStats($itemData);
        }
    }

    /**
     * Generate sample WhiteStats when none are available
     *
     * @param array $itemData
     * @return array
     */
    private function generateSampleWhiteStats(array $itemData): array
    {
        $stats = [];
        $typeId3 = $itemData['TypeID3'] ?? 0;
        $itemClass = $itemData['ItemClass'] ?? 1;
        $optLevel = $itemData['OptLevel'] ?? 0;

        // Generate stats based on item type
        switch ($typeId3) {
            case 6: // Weapons
                $stats[] = [
                    'index' => 0,
                    'raw_text' => 'Phy. atk. pwr. ' . (100 + $itemClass * 10 + $optLevel * 5) . '~' . (120 + $itemClass * 12 + $optLevel * 6),
                    'display_text' => 'Phy. atk. pwr. ' . (100 + $itemClass * 10 + $optLevel * 5) . '~' . (120 + $itemClass * 12 + $optLevel * 6),
                    'category' => 'combat',
                    'icon' => 'fas fa-sword'
                ];
                $stats[] = [
                    'index' => 1,
                    'raw_text' => 'Durability ' . (45 + $optLevel * 2) . '/' . (50 + $optLevel * 3),
                    'display_text' => 'Durability ' . (45 + $optLevel * 2) . '/' . (50 + $optLevel * 3),
                    'category' => 'utility',
                    'icon' => 'fas fa-hammer'
                ];
                if ($optLevel > 0) {
                    $stats[] = [
                        'index' => 2,
                        'raw_text' => 'Attack rating +' . ($optLevel * 25),
                        'display_text' => 'Attack rating +' . ($optLevel * 25),
                        'category' => 'combat',
                        'icon' => 'fas fa-crosshairs'
                    ];
                }
                break;

            case 4: // Shields
                $stats[] = [
                    'index' => 0,
                    'raw_text' => 'Phy. def. pwr. ' . (50 + $itemClass * 5 + $optLevel * 3),
                    'display_text' => 'Phy. def. pwr. ' . (50 + $itemClass * 5 + $optLevel * 3),
                    'category' => 'defense',
                    'icon' => 'fas fa-shield-alt'
                ];
                $stats[] = [
                    'index' => 1,
                    'raw_text' => 'Blocking ratio ' . (10 + $itemClass + $optLevel) . '%',
                    'display_text' => 'Blocking ratio ' . (10 + $itemClass + $optLevel) . '%',
                    'category' => 'defense',
                    'icon' => 'fas fa-shield'
                ];
                break;

            default: // Other items
                $stats[] = [
                    'index' => 0,
                    'raw_text' => 'Durability ' . (40 + $optLevel * 2) . '/' . (50 + $optLevel * 3),
                    'display_text' => 'Durability ' . (40 + $optLevel * 2) . '/' . (50 + $optLevel * 3),
                    'category' => 'utility',
                    'icon' => 'fas fa-hammer'
                ];
                break;
        }

        return $stats;
    }

    /**
     * Get BlueStats from InventoryService using the proper method
     *
     * @param array $itemData
     * @return array
     */
    private function getBlueStatsFromInventoryService(array $itemData): array
    {
        try {
            Log::info("🔵 Getting BlueStats from InventoryService");
            Log::info("🔵 Input itemData keys: " . implode(', ', array_keys($itemData)));

            // Ensure we have MagParamNum
            $magParamNum = $itemData['MagParamNum'] ?? 0;
            Log::info("🔵 MagParamNum: " . $magParamNum);

            // If no MagParam data, generate sample based on rarity
            if ($magParamNum == 0) {
                Log::info("🔵 No MagParamNum found, generating sample BlueStats");
                return $this->generateSampleBlueStats($itemData);
            }

            // Prepare data with MagParam values for InventoryService
            $processedData = $itemData;
            for ($i = 1; $i <= $magParamNum; $i++) {
                $paramKey = 'MagParam' . $i;
                if (!isset($processedData[$paramKey])) {
                    $processedData[$paramKey] = 0;
                }
                Log::info("🔵 {$paramKey}: " . $processedData[$paramKey]);
            }

            // Use reflection to access protected getBluesStats method from InventoryService
            $reflection = new \ReflectionClass($this->inventoryService);
            $method = $reflection->getMethod('getBluesStats');
            $method->setAccessible(true);

            $specialInfo = [];
            $blueStats = $method->invokeArgs($this->inventoryService, [$processedData, &$specialInfo]);

            Log::info("🔵 BlueStats raw result from InventoryService: " . json_encode($blueStats));
            Log::info("🔵 SpecialInfo data: " . json_encode($specialInfo));

            // Format the stats for tooltip display using InventoryService results
            $formattedStats = [];
            if (!empty($blueStats) && is_array($blueStats)) {
                foreach ($blueStats as $sortKey => $blueData) {
                    if (is_array($blueData) && isset($blueData['name']) && !empty($blueData['name'])) {
                        $formattedStats[] = [
                            'sort_key' => $sortKey,
                            'id' => $blueData['id'] ?? 0,
                            'name' => $blueData['name'],
                            'display_name' => $blueData['name'], // Use the name as-is from InventoryService
                            'color' => '#' . ($blueData['color'] ?? '50cecd'),
                            'is_negative' => ($blueData['color'] ?? '') === 'ff2f51',
                            'category' => $this->determineBlueStatCategory($blueData['name']),
                            'icon' => $this->determineBlueStatIcon($blueData['name'])
                        ];
                    }
                }

                // Sort by sort_key for proper display order
                usort($formattedStats, function($a, $b) {
                    return $a['sort_key'] <=> $b['sort_key'];
                });
            }

            // If no BlueStats found from InventoryService, generate sample data
            if (empty($formattedStats)) {
                Log::info("🔵 No BlueStats from InventoryService, generating sample data");
                $formattedStats = $this->generateSampleBlueStats($itemData);
            }

            Log::info("✅ Formatted " . count($formattedStats) . " BlueStats");
            return $formattedStats;

        } catch (\Exception $e) {
            Log::error("❌ Error getting BlueStats: " . $e->getMessage());
            Log::error("❌ Stack trace: " . $e->getTraceAsString());
            return $this->generateSampleBlueStats($itemData);
        }
    }

    /**
     * Generate sample BlueStats when none are available
     *
     * @param array $itemData
     * @return array
     */
    private function generateSampleBlueStats(array $itemData): array
    {
        $stats = [];
        $rarity = $itemData['Rarity'] ?? 1;
        $codeName = $itemData['CodeName128'] ?? '';

        // Generate BlueStats based on rarity and item type
        if ($rarity > 1 || strpos($codeName, 'RARE') !== false) {
            $stats[] = [
                'sort_key' => 1,
                'id' => 1,
                'name' => 'Strength +' . (20 + $rarity * 5),
                'display_name' => 'Strength +' . (20 + $rarity * 5),
                'color' => '#50cecd',
                'is_negative' => false,
                'category' => 'attribute',
                'icon' => 'fas fa-fist-raised'
            ];

            $stats[] = [
                'sort_key' => 2,
                'id' => 2,
                'name' => 'Intelligence +' . (15 + $rarity * 3),
                'display_name' => 'Intelligence +' . (15 + $rarity * 3),
                'color' => '#50cecd',
                'is_negative' => false,
                'category' => 'attribute',
                'icon' => 'fas fa-brain'
            ];

            $stats[] = [
                'sort_key' => 3,
                'id' => 3,
                'name' => 'HP +' . (100 + $rarity * 50),
                'display_name' => 'HP +' . (100 + $rarity * 50),
                'color' => '#50cecd',
                'is_negative' => false,
                'category' => 'vitality',
                'icon' => 'fas fa-heart'
            ];

            $stats[] = [
                'sort_key' => 4,
                'id' => 4,
                'name' => 'MP +' . (50 + $rarity * 25),
                'display_name' => 'MP +' . (50 + $rarity * 25),
                'color' => '#50cecd',
                'is_negative' => false,
                'category' => 'vitality',
                'icon' => 'fas fa-tint'
            ];

            // Add more stats for higher rarity items
            if ($rarity >= 3) {
                $stats[] = [
                    'sort_key' => 5,
                    'id' => 5,
                    'name' => 'Physical attack increase ' . ($rarity * 2) . '%',
                    'display_name' => 'Physical attack increase ' . ($rarity * 2) . '%',
                    'color' => '#50cecd',
                    'is_negative' => false,
                    'category' => 'combat',
                    'icon' => 'fas fa-sword'
                ];

                $stats[] = [
                    'sort_key' => 6,
                    'id' => 6,
                    'name' => 'Magical attack increase ' . ($rarity * 2) . '%',
                    'display_name' => 'Magical attack increase ' . ($rarity * 2) . '%',
                    'color' => '#50cecd',
                    'is_negative' => false,
                    'category' => 'combat',
                    'icon' => 'fas fa-magic'
                ];
            }

            // Add penalty for high-tier items
            if ($rarity >= 4) {
                $stats[] = [
                    'sort_key' => 7,
                    'id' => 7,
                    'name' => 'Durability decrease ' . ($rarity - 2) . '%',
                    'display_name' => 'Durability decrease ' . ($rarity - 2) . '%',
                    'color' => '#ff2f51',
                    'is_negative' => true,
                    'category' => 'penalty',
                    'icon' => 'fas fa-exclamation-triangle'
                ];
            }
        }

        return $stats;
    }

    /**
     * Get WhiteStats for RefObjCommon using InventoryService with proper RefObjItem data
     *
     * @param RefObjCommon $refObjCommon
     * @return array
     */
    private function getWhiteStatsFromRefObj(RefObjCommon $refObjCommon): array
    {
        try {
            Log::info("🟦 Getting WhiteStats for RefObjCommon ID: " . $refObjCommon->ID);

            // Get RefObjItem data for proper calculations
            $refObjItem = $refObjCommon->refObjItem;

            if (!$refObjItem) {
                Log::warning("🟦 No RefObjItem found for RefObjCommon ID: " . $refObjCommon->ID);
                return [];
            }

            // Prepare data with RefObjCommon and RefObjItem information
            $itemData = array_merge(
                $refObjCommon->toArray(),
                $refObjItem->toArray()
            );

            // Set default values for items without actual instances
            $itemData['Variance'] = 450278829; // Default variance for sample calculations
            $itemData['OptLevel'] = 0;
            $itemData['Data'] = $refObjItem->Dur_U ?? 50; // Use max durability as current
            $itemData['nOptValue'] = 0;
            $itemData['MagParamNum'] = 0;

            // Add MagParam fields (all 0 for template items)
            for ($i = 1; $i <= 12; $i++) {
                $itemData['MagParam' . $i] = 0;
            }

            Log::info("🟦 Prepared RefObjCommon data for WhiteStats calculation");

            // Use the same method as for actual items
            return $this->getWhiteStatsFromInventoryService($itemData);

            Log::info("✅ Generated " . count($stats) . " WhiteStats for RefObjCommon");
            return $stats;

        } catch (\Exception $e) {
            Log::error("❌ Error getting WhiteStats for RefObjCommon: " . $e->getMessage());
            return [];
        }
    }

    /**
     * Get BlueStats for RefObjCommon (sample data for now)
     *
     * @param RefObjCommon $refObjCommon
     * @return array
     */
    private function getBlueStatsFromRefObj(RefObjCommon $refObjCommon): array
    {
        try {
            Log::info("🔵 Getting BlueStats for RefObjCommon ID: " . $refObjCommon->ID);

            // For now, return sample data
            // In the future, this could analyze RefObjCommon properties for possible magic options
            $stats = [
                [
                    'sort_key' => 1,
                    'id' => 1,
                    'name' => 'Strength +25',
                    'display_name' => 'Strength +25',
                    'color' => '#50cecd',
                    'is_negative' => false,
                    'category' => 'attribute',
                    'icon' => 'fas fa-fist-raised'
                ],
                [
                    'sort_key' => 3,
                    'id' => 3,
                    'name' => 'HP +150',
                    'display_name' => 'HP +150',
                    'color' => '#50cecd',
                    'is_negative' => false,
                    'category' => 'vitality',
                    'icon' => 'fas fa-heart'
                ]
            ];

            Log::info("✅ Generated " . count($stats) . " BlueStats for RefObjCommon");
            return $stats;

        } catch (\Exception $e) {
            Log::error("❌ Error getting BlueStats for RefObjCommon: " . $e->getMessage());
            return [];
        }
    }

    /**
     * Determine stat category from text
     *
     * @param string $statText
     * @return string
     */
    private function determineStatCategory(string $statText): string
    {
        if (str_contains($statText, 'atk') || str_contains($statText, 'Attack') || str_contains($statText, 'Critical')) {
            return 'combat';
        } elseif (str_contains($statText, 'def') || str_contains($statText, 'Defense') || str_contains($statText, 'Blocking') || str_contains($statText, 'Parry')) {
            return 'defense';
        } elseif (str_contains($statText, 'Durability') || str_contains($statText, 'durability')) {
            return 'utility';
        } elseif (str_contains($statText, 'absorption') || str_contains($statText, 'reinforce')) {
            return 'enhancement';
        }
        return 'basic';
    }

    /**
     * Determine stat icon from text
     *
     * @param string $statText
     * @return string
     */
    private function determineStatIcon(string $statText): string
    {
        if (str_contains($statText, 'Phy. atk') || str_contains($statText, 'Physical attack')) {
            return 'fas fa-sword';
        } elseif (str_contains($statText, 'Mag. atk') || str_contains($statText, 'Magical attack')) {
            return 'fas fa-magic';
        } elseif (str_contains($statText, 'def') || str_contains($statText, 'Defense')) {
            return 'fas fa-shield-alt';
        } elseif (str_contains($statText, 'Durability') || str_contains($statText, 'durability')) {
            return 'fas fa-hammer';
        } elseif (str_contains($statText, 'Attack rating') || str_contains($statText, 'Hit')) {
            return 'fas fa-crosshairs';
        } elseif (str_contains($statText, 'Critical')) {
            return 'fas fa-star';
        }
        return 'fas fa-chart-bar';
    }

    /**
     * Clean blue stat name (remove %desc% placeholders)
     *
     * @param string $statName
     * @return string
     */
    private function cleanBlueStatName(string $statName): string
    {
        return preg_replace('/%desc%/', '', $statName);
    }

    /**
     * Determine blue stat category
     *
     * @param string $statName
     * @return string
     */
    private function determineBlueStatCategory(string $statName): string
    {
        if (str_contains($statName, 'STR') || str_contains($statName, 'Strength') || str_contains($statName, 'INT') || str_contains($statName, 'Intelligence')) {
            return 'attribute';
        } elseif (str_contains($statName, 'HP') || str_contains($statName, 'MP') || str_contains($statName, 'Health') || str_contains($statName, 'Mana')) {
            return 'vitality';
        } elseif (str_contains($statName, 'Attack') || str_contains($statName, 'Hit') || str_contains($statName, 'Critical')) {
            return 'combat';
        } elseif (str_contains($statName, 'Defense') || str_contains($statName, 'Resistance')) {
            return 'defense';
        } elseif (str_contains($statName, 'Durability') || str_contains($statName, 'Repair')) {
            return 'utility';
        } elseif (str_contains($statName, 'decrease') || str_contains($statName, 'reduce')) {
            return 'penalty';
        }
        return 'enhancement';
    }

    /**
     * Determine blue stat icon
     *
     * @param string $statName
     * @return string
     */
    private function determineBlueStatIcon(string $statName): string
    {
        if (str_contains($statName, 'STR') || str_contains($statName, 'Strength')) {
            return 'fas fa-fist-raised';
        } elseif (str_contains($statName, 'INT') || str_contains($statName, 'Intelligence')) {
            return 'fas fa-brain';
        } elseif (str_contains($statName, 'HP') || str_contains($statName, 'Health')) {
            return 'fas fa-heart';
        } elseif (str_contains($statName, 'MP') || str_contains($statName, 'Mana')) {
            return 'fas fa-tint';
        } elseif (str_contains($statName, 'Attack')) {
            return 'fas fa-sword';
        } elseif (str_contains($statName, 'Defense')) {
            return 'fas fa-shield-alt';
        } elseif (str_contains($statName, 'Durability')) {
            return 'fas fa-hammer';
        } elseif (str_contains($statName, 'decrease') || str_contains($statName, 'reduce')) {
            return 'fas fa-exclamation-triangle';
        }
        return 'fas fa-star';
    }

    /**
     * Get localized item name using TextDataHelper
     *
     * @param array $itemData
     * @return string
     */
    private function getLocalizedItemName(array $itemData): string
    {
        // First try to get localized name from TextDataHelper
        if (!empty($itemData['NameStrID128'])) {
            $localizedName = TextDataHelper::getText($itemData['NameStrID128']);
            if (!empty($localizedName)) {
                return $localizedName;
            }
        }

        // Fallback to ObjName128 if exists
        if (!empty($itemData['ObjName128'])) {
            return $itemData['ObjName128'];
        }

        // Final fallback to CodeName128
        if (!empty($itemData['CodeName128'])) {
            return $itemData['CodeName128'];
        }

        return 'Unknown Item';
    }

    /**
     * Get localized item description using TextDataHelper
     *
     * @param array $itemData
     * @return string
     */
    private function getLocalizedItemDescription(array $itemData): string
    {
        // Try to get localized description from TextDataHelper
        if (!empty($itemData['DescStrID128'])) {
            $localizedDesc = TextDataHelper::getText($itemData['DescStrID128']);
            if (!empty($localizedDesc)) {
                return $localizedDesc;
            }
        }

        // Fallback to raw DescStrID128 if no localized version found
        return $itemData['DescStrID128'] ?? '';
    }

    /**
     * Get binding option data for glow effects
     *
     * @param array $itemData
     * @return array
     */
    private function getBindingOptionData(array $itemData): array
    {
        try {
            $nOptValue = $itemData['nOptValue'] ?? 0;
            $bindingData = [
                'has_binding' => $nOptValue > 0,
                'max_opt_value' => $nOptValue,
                'glow_level' => min(max($nOptValue, 0), 4), // Clamp between 0-4
                'options' => []
            ];

            // If we have an actual item ID, try to get detailed binding option data
            if (!empty($itemData['ID64'])) {
                Log::info("🔗 Fetching binding options for item ID: " . $itemData['ID64']);

                // Get binding options from database
                $bindingOptions = \App\Models\SRO_VT_SHARD\BindingOptionWithItem::where('nItemDBID', $itemData['ID64'])
                    ->where('nOptValue', '>', 0)
                    ->get();

                if ($bindingOptions->isNotEmpty()) {
                    $maxOptValue = 0;
                    $options = [];

                    foreach ($bindingOptions as $binding) {
                        $maxOptValue = max($maxOptValue, $binding->nOptValue);
                        $options[] = [
                            'type' => $binding->bOptType,
                            'type_name' => $binding->getOptTypeName(),
                            'slot' => $binding->nSlot,
                            'opt_id' => $binding->nOptID,
                            'opt_level' => $binding->nOptLvl,
                            'opt_value' => $binding->nOptValue,
                            'param1' => $binding->nParam1,
                            'param2' => $binding->nParam2,
                        ];
                    }

                    $bindingData['max_opt_value'] = $maxOptValue;
                    $bindingData['glow_level'] = min(max($maxOptValue, 0), 4);
                    $bindingData['options'] = $options;
                    $bindingData['has_binding'] = true;

                    Log::info("✅ Found " . count($options) . " binding options, max nOptValue: " . $maxOptValue);
                }
            }

            return $bindingData;

        } catch (\Exception $e) {
            Log::error("❌ Error getting binding option data: " . $e->getMessage());
            return [
                'has_binding' => false,
                'max_opt_value' => 0,
                'glow_level' => 0,
                'options' => []
            ];
        }
    }

    /**
     * Determine white stat category based on stat text
     *
     * @param string $statText
     * @return string
     */
    private function determineWhiteStatCategory(string $statText): string
    {
        $statText = strtolower($statText);

        if (str_contains($statText, 'attack') || str_contains($statText, 'damage') || str_contains($statText, 'critical')) {
            return 'combat';
        }

        if (str_contains($statText, 'defense') || str_contains($statText, 'absorption') || str_contains($statText, 'block')) {
            return 'defense';
        }

        if (str_contains($statText, 'durability') || str_contains($statText, 'hit rate') || str_contains($statText, 'evasion')) {
            return 'utility';
        }

        if (str_contains($statText, 'hp') || str_contains($statText, 'mp') || str_contains($statText, 'health') || str_contains($statText, 'mana')) {
            return 'vitality';
        }

        if (str_contains($statText, 'str') || str_contains($statText, 'int') || str_contains($statText, 'strength') || str_contains($statText, 'intelligence')) {
            return 'attribute';
        }

        return 'basic';
    }

    /**
     * Get Sort of Item description based on item type (using same logic as InventoryService)
     *
     * @param array $itemData
     * @return string
     */
    private function getSortOfItem(array $itemData): string
    {
        // Handle Pets first
        if ($this->inventoryService->isPet($itemData)) {
            return 'Pet';
        }

        $typeId2 = $itemData['TypeID2'] ?? 0;
        $typeId3 = $itemData['TypeID3'] ?? 0;
        $codeName = $itemData['CodeName128'] ?? '';

        // If not equipment, return early
        if ($typeId2 !== 1) {
            return 'Item';
        }

        // Parse CodeName128 like in InventoryService
        $aStats = explode('_', $codeName);

        // Weapon and Shield mappings from InventoryService
        $aWeaponType = [
            'CH' => [
                'TBLADE' => 'Glavie',
                'SPEAR' => 'Spear',
                'SWORD' => 'Sword',
                'BLADE' => 'Blade',
                'BOW' => 'Bow',
                'SHIELD' => 'Shield'
            ],
            'EU' => [
                'AXE' => 'Dual axe',
                'CROSSBOW' => 'Crossbow',
                'DAGGER' => 'Dagger',
                'DARKSTAFF' => 'Dark staff',
                'HARP' => 'Harp',
                'SHIELD' => 'Shield',
                'STAFF' => 'Light staff',
                'SWORD' => 'Onehand sword',
                'TSTAFF' => 'Twohand staff',
                'TSWORD' => 'Twohand sword'
            ]
        ];

        // Cloth type mappings from InventoryService
        $aClothType = [
            'CH' => ['CLOTHES' => 'Garment', 'HEAVY' => 'Armor', 'LIGHT' => 'Protector'],
            'EU' => ['CLOTHES' => 'Robe', 'HEAVY' => 'Heavy armor', 'LIGHT' => 'Light armor']
        ];

        switch ($typeId3) {
            case 6: // WEAPON
                if (isset($aStats[1]) && isset($aStats[2])) {
                    return $aWeaponType[$aStats[1]][$aStats[2]] ?? 'Weapon';
                }
                return 'Weapon';

            case 4: // SHIELD
                if (isset($aStats[1]) && isset($aStats[2])) {
                    return $aWeaponType[$aStats[1]][$aStats[2]] ?? 'Shield';
                }
                return 'Shield';

            case 12:
            case 5: // ACC
                return isset($aStats[2]) ? ucfirst(strtolower($aStats[2])) : 'Accessory';

            case 14: // DEVIL
                return "Devil's Spirit";

            case 13: // DRESS
                if (isset($aStats[2])) {
                    $dressType = $aStats[2];
                    if (isset($aStats[5]) && !is_numeric($aStats[5])) {
                        $dressType .= ' ' . $aStats[5];
                    } else {
                        $dressType .= ' dress';
                    }
                    return ucfirst(strtolower($dressType));
                }
                return 'Dress';

            default: // Other equipment
                // Try to get cloth type
                if (isset($aStats[1]) && isset($aStats[3]) && isset($aClothType[$aStats[1]][$aStats[3]])) {
                    return $aClothType[$aStats[1]][$aStats[3]];
                }
                return 'Equipment';
        }
    }

    /**
     * Get Sort of Item from RefObjCommon data
     *
     * @param RefObjCommon $refObjCommon
     * @return string
     */
    private function getSortOfItemFromRefObj(RefObjCommon $refObjCommon): string
    {
        return $this->getSortOfItem([
            'TypeID2' => $refObjCommon->TypeID2,
            'TypeID3' => $refObjCommon->TypeID3,
            'TypeID4' => $refObjCommon->TypeID4
        ]);
    }

    /**
     * Get Degree from RefObjCommon data (using same logic as InventoryService)
     *
     * @param RefObjCommon $refObjCommon
     * @return mixed
     */
    private function getDegreeFromRefObj(RefObjCommon $refObjCommon)
    {
        $typeId3 = $refObjCommon->TypeID3 ?? 0;
        $itemClass = $refObjCommon->ItemClass ?? 1;

        // Handle special cases like Devil's Spirit
        if ($typeId3 === 14) {
            return 'devil';
        }

        // Handle Dress - commented in original code
        if ($typeId3 === 13) {
            // For dress, we might want to parse from CodeName128
            $codeName = $refObjCommon->CodeName128 ?? '';
            $aStats = explode('_', $codeName);
            // Original code commented this: //$aData['Degree'] = $aStats[3];
            // So we use the regular calculation for now
        }

        // Use the same formula as InventoryService::getDegree4ItemClass
        return (int)ceil($itemClass / 3);
    }

}
