<?php

namespace App\Helpers;

use App\Models\SRO_VT_SHARD\Inventory;
use App\Models\SRO_VT_SHARD\Items;
use App\Models\SRO_VT_SHARD\RefObjCommon;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class InventoryHelper
{
    /**
     * Get character equipment items (equipped items only - slots 0-12)
     *
     * @param int $charId
     * @return array
     */
    public static function getCharacterEquipment($charId)
    {
        try {
            $equipmentSlots = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];

            $equipment = DB::connection('sqlsrv_shard')
                ->table('dbo._Inventory as inv')
                ->join('dbo._Items as items', 'inv.ItemID', '=', 'items.ID64')
                ->join('dbo._RefObjCommon as ref', 'items.RefItemID', '=', 'ref.ID')
                ->select([
                    'inv.slot',
                    'inv.ItemID as item_id',
                    'items.OptLevel as opt_level',
                    'items.RefItemID',
                    'ref.CodeName128 as code_name',
                    'ref.ObjName128 as obj_name',
                    'ref.NameStrID128 as name_str_id',
                    'ref.DescStrID128 as desc_str_id',
                    'ref.AssocFileIcon128 as icon_path',
                    'ref.Rarity as rarity'
                ])
                ->where('inv.CharID', $charId)
                ->whereIn('inv.slot', $equipmentSlots)
                ->whereNotNull('inv.ItemID')
                ->where('inv.ItemID', '>', 0)
                ->get();

            $processedEquipment = [];

            foreach ($equipment as $item) {
                // Get localized name or fallback
                $displayName = \App\Helpers\TextDataHelper::getText($item->name_str_id);
                if (empty($displayName)) {
                    $displayName = $item->obj_name ?: $item->code_name ?: 'Unknown Item';
                }

                $processedEquipment[] = [
                    'slot' => $item->slot,
                    'item_id' => $item->item_id,
                    'name' => $displayName,
                    'code_name' => $item->code_name,
                    'icon_path' => $item->icon_path,
                    'rarity' => $item->rarity ?? 1,
                    'opt_level' => $item->opt_level ?? 0,
                    'ref_item_id' => $item->RefItemID,
                    'ref_obj_id' => $item->RefItemID, // Add this for tooltip system
                    'RefItemID' => $item->RefItemID, // Keep compatibility
                    'name_str_id' => $item->name_str_id,
                    'desc_str_id' => $item->desc_str_id
                ];
            }

            return $processedEquipment;

        } catch (\Exception $e) {
            Log::error('Error fetching character equipment: ' . $e->getMessage(), [
                'char_id' => $charId,
                'trace' => $e->getTraceAsString()
            ]);
            return [];
        }
    }

    /**
     * Get character's full inventory (all slots)
     *
     * @param int $charId
     * @return array
     */
    public static function getCharacterInventory($charId)
    {
        try {
            $inventory = DB::connection('sqlsrv_shard')
                ->table('dbo._Inventory as inv')
                ->join('dbo._Items as items', 'inv.ItemID', '=', 'items.ID64')
                ->join('dbo._RefObjCommon as ref', 'items.RefItemID', '=', 'ref.ID')
                ->select([
                    'inv.slot',
                    'inv.ItemID as item_id',
                    'items.OptLevel as opt_level',
                    'items.RefItemID',
                    'items.Variance',
                    'ref.CodeName128 as name',
                    'ref.AssocFileIcon128 as icon_path',
                    'ref.Rarity as rarity',
                    'ref.TypeID1',
                    'ref.TypeID2',
                    'ref.TypeID3',
                    'ref.TypeID4'
                ])
                ->where('inv.CharID', $charId)
                ->whereNotNull('inv.ItemID')
                ->where('inv.ItemID', '>', 0)
                ->orderBy('inv.slot')
                ->get();

            $processedInventory = [];

            foreach ($inventory as $item) {
                $processedInventory[] = [
                    'slot' => $item->slot,
                    'item_id' => $item->item_id,
                    'name' => $item->name ?? 'Unknown Item',
                    'icon_path' => $item->icon_path,
                    'rarity' => $item->rarity ?? 1,
                    'opt_level' => $item->opt_level ?? 0,
                    'ref_item_id' => $item->RefItemID,
                    'variance' => $item->Variance ?? 0,
                    'type_ids' => [
                        $item->TypeID1 ?? 0,
                        $item->TypeID2 ?? 0,
                        $item->TypeID3 ?? 0,
                        $item->TypeID4 ?? 0
                    ]
                ];
            }

            return $processedInventory;

        } catch (\Exception $e) {
            Log::error('Error fetching character inventory: ' . $e->getMessage(), [
                'char_id' => $charId,
                'trace' => $e->getTraceAsString()
            ]);
            return [];
        }
    }

    /**
     * Get item details by Item ID
     *
     * @param string $itemId
     * @return array|null
     */
    public static function getItemDetails($itemId)
    {
        try {
            $item = DB::connection('sqlsrv_shard')
                ->table('dbo._Items as items')
                ->join('dbo._RefObjCommon as ref', 'items.RefItemID', '=', 'ref.ID')
                ->select([
                    'items.ID64 as item_id',
                    'items.OptLevel as opt_level',
                    'items.RefItemID',
                    'items.Variance',
                    'ref.CodeName128 as name',
                    'ref.AssocFileIcon128 as icon_path',
                    'ref.Rarity as rarity',
                    'ref.TypeID1',
                    'ref.TypeID2',
                    'ref.TypeID3',
                    'ref.TypeID4'
                ])
                ->where('items.ID64', $itemId)
                ->first();

            if (!$item) {
                return null;
            }

            return [
                'item_id' => $item->item_id,
                'name' => $item->name ?? 'Unknown Item',
                'icon_path' => $item->icon_path,
                'rarity' => $item->rarity ?? 1,
                'opt_level' => $item->opt_level ?? 0,
                'ref_item_id' => $item->RefItemID,
                'variance' => $item->Variance ?? 0,
                'type_ids' => [
                    $item->TypeID1 ?? 0,
                    $item->TypeID2 ?? 0,
                    $item->TypeID3 ?? 0,
                    $item->TypeID4 ?? 0
                ]
            ];

        } catch (\Exception $e) {
            Log::error('Error fetching item details: ' . $e->getMessage(), [
                'item_id' => $itemId,
                'trace' => $e->getTraceAsString()
            ]);
            return null;
        }
    }

    /**
     * Convert icon path from .ddj to .jpg and add assets prefix
     *
     * @param string|null $iconPath
     * @return string|null
     */
    public static function processIconPath($iconPath)
    {
        if (!$iconPath) {
            return '/assets/images/ui/placeholder-item.svg';
        }

        // Clean the path
        $cleanPath = trim($iconPath);
        $cleanPath = str_replace('\\', '/', $cleanPath);

        // Replace .ddj with .jpg and add assets prefix
        $processedPath = '/assets/images/sro/' . str_replace('.ddj', '.jpg', $cleanPath);

        // Check if file exists and provide fallback
        $fullPath = public_path('assets/images/sro/' . str_replace('.ddj', '.jpg', $cleanPath));

        if (!file_exists($fullPath)) {
            // Try some common fallback paths based on existing files
            $fallbacks = [
                '/assets/images/sro/item/1.jpg',
                '/assets/images/sro/item/2.jpg',
                '/assets/images/sro/item/3.jpg',
                '/assets/images/ui/placeholder-item.svg'
            ];

            foreach ($fallbacks as $fallback) {
                if (file_exists(public_path(ltrim($fallback, '/')))) {
                    Log::warning("Icon not found, using fallback: {$iconPath} -> {$fallback}");
                    return $fallback;
                }
            }

            Log::warning("Icon not found and no fallback available: {$iconPath}");
            return '/assets/images/ui/placeholder-item.svg';
        }

        return $processedPath;
    }    /**
     * Get item grade based on rarity
     *
     * @param int $rarity
     * @return string
     */
    public static function getItemGrade($rarity)
    {
        switch ($rarity) {
            case 1:
                return 'normal';
            case 2:
                return 'rare';
            case 3:
                return 'epic';
            case 4:
                return 'legendary';
            case 5:
                return 'mythic';
            default:
                return 'normal';
        }
    }

    /**
     * Check if slot is equipment slot (0-12)
     *
     * @param int $slot
     * @return bool
     */
    public static function isEquipmentSlot($slot)
    {
        return in_array($slot, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]);
    }

    /**
     * Get slot name by slot number
     *
     * @param int $slot
     * @return string
     */
    public static function getSlotName($slot)
    {
        $slotNames = [
            0 => 'Head',
            1 => 'Chest',
            2 => 'Shoulder',
            3 => 'Hand',
            4 => 'Legs',
            5 => 'Foot',
            6 => 'Weapon',
            7 => 'Shield',
            8 => 'Job-item',
            9 => 'Earring',
            10 => 'Necklace',
            11 => 'Left-Ring',
            12 => 'Right-Ring'
        ];

        return $slotNames[$slot] ?? 'Unknown';
    }

    /**
     * Format equipment data for frontend
     *
     * @param array $equipment
     * @return array
     */
    public static function formatEquipmentForFrontend($equipment)
    {
        $formatted = [];

        foreach ($equipment as $item) {
            $formatted[] = [
                'slot' => $item['slot'],
                'item_id' => $item['item_id'],
                'name' => $item['name'],
                'icon_path' => $item['icon_path'],
                'rarity' => $item['rarity'],
                'opt_level' => $item['opt_level'],
                'ref_item_id' => $item['ref_item_id'] ?? null
            ];
        }

        return $formatted;
    }

    /**
     * Alternative method: Get character equipment using InventoryTooltipController logic directly
     * This method uses the exact same logic as InventoryTooltipController
     *
     * @param int $charId
     * @return array
     */
    public static function getCharacterEquipmentViaTooltipController($charId)
    {
        try {
            // First, get the equipped items
            $equippedItems = self::getCharacterEquipment($charId);

            if (empty($equippedItems)) {
                return [];
            }

            $enhancedEquipment = [];

            // For each equipped item, use InventoryTooltipController logic
            foreach ($equippedItems as $equippedItem) {
                $refObjId = $equippedItem['ref_obj_id'] ?? $equippedItem['RefItemID'];

                if (!$refObjId) {
                    $enhancedEquipment[] = $equippedItem;
                    continue;
                }

                // Use InventoryTooltipController's findActualItemInstance logic
                $actualItem = self::findActualItemInstanceTooltipStyle($refObjId);

                if ($actualItem) {
                    // Merge the equipped item data with enhanced data
                    $enhancedItem = array_merge($equippedItem, [
                        'opt_level' => (int)($actualItem['OptLevel'] ?? 0),
                        'mag_param_num' => (int)($actualItem['MagParamNum'] ?? 0),
                        'variance' => (int)($actualItem['Variance'] ?? 0),
                        'enhanced_from_tooltip' => true,
                        'tooltip_source' => $actualItem['found_by'] ?? 'unknown'
                    ]);

                    $enhancedEquipment[] = $enhancedItem;
                } else {
                    // Keep original if no enhanced version found
                    $enhancedEquipment[] = array_merge($equippedItem, [
                        'enhanced_from_tooltip' => false
                    ]);
                }
            }

            Log::info("✅ InventoryHelper: Enhanced equipment using pure InventoryTooltipController logic for character {$charId}");
            return $enhancedEquipment;

        } catch (\Exception $e) {
            Log::error('Error getting character equipment via InventoryTooltipController: ' . $e->getMessage(), [
                'char_id' => $charId
            ]);
            return [];
        }
    }

    /**
     * Pure InventoryTooltipController findActualItemInstance logic
     *
     * @param int $itemId
     * @return array|null
     */
    private static function findActualItemInstanceTooltipStyle($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;
    }

    /**
     * Find actual item instance with enhanced data using same logic as InventoryTooltipController
     * This method mirrors the exact logic from InventoryTooltipController::findActualItemInstance()
     *
     * @param int $refObjId
     * @return array|null
     */
    public static function findActualItemInstance($refObjId)
    {
        try {
            // First tier: Find items with actual magic options or variance (same as InventoryTooltipController)
            $items = Items::with(['refObjCommon.refObjItem'])
                ->whereHas('refObjCommon', function($query) use ($refObjId) {
                    $query->where('ID', $refObjId);
                })
                ->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 (same logic as InventoryTooltipController)
                $bestItem = $items->sortByDesc('MagParamNum')->first();

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

                // Return as array with combined data (same format as InventoryTooltipController)
                $data = array_merge(
                    $bestItem->toArray(),
                    $bestItem->refObjCommon ? $bestItem->refObjCommon->toArray() : [],
                    $bestItem->refObjCommon->refObjItem ? $bestItem->refObjCommon->refObjItem->toArray() : []
                );
                $data['found_by'] = 'ActualItem';
                return $data;
            }

            // Second tier: Find any item of this type if no enhanced items found
            $anyItem = Items::with(['refObjCommon.refObjItem'])
                ->whereHas('refObjCommon', function($query) use ($refObjId) {
                    $query->where('ID', $refObjId);
                })
                ->first();

            if ($anyItem) {
                Log::info("🎯 InventoryHelper: 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('InventoryHelper: Error finding actual item instance: ' . $e->getMessage());
        }

        return null;
    }

    /**
     * Get enhanced character equipment with proper opt_level from actual items
     * Uses InventoryTooltipController logic for consistent data retrieval
     *
     * @param int $charId
     * @return array
     */
    public static function getEnhancedCharacterEquipment($charId)
    {
        try {
            $equipmentSlots = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];

            $equipment = DB::connection('sqlsrv_shard')
                ->table('dbo._Inventory as inv')
                ->join('dbo._Items as items', 'inv.ItemID', '=', 'items.ID64')
                ->join('dbo._RefObjCommon as ref', 'items.RefItemID', '=', 'ref.ID')
                ->select([
                    'inv.slot',
                    'inv.ItemID as item_id',
                    'items.OptLevel as equipped_opt_level',
                    'items.MagParamNum as equipped_mag_param_num',
                    'items.Variance as equipped_variance',
                    'items.RefItemID as ref_obj_id',
                    'ref.CodeName128 as code_name',
                    'ref.ObjName128 as obj_name',
                    'ref.NameStrID128 as name_str_id',
                    'ref.DescStrID128 as desc_str_id',
                    'ref.AssocFileIcon128 as icon_path',
                    'ref.Rarity as rarity'
                ])
                ->where('inv.CharID', $charId)
                ->whereIn('inv.slot', $equipmentSlots)
                ->whereNotNull('inv.ItemID')
                ->where('inv.ItemID', '>', 0)
                ->get();

            $processedEquipment = [];

            foreach ($equipment as $item) {
                // Get localized name or fallback
                $displayName = \App\Helpers\TextDataHelper::getText($item->name_str_id);
                if (empty($displayName)) {
                    $displayName = $item->obj_name ?: $item->code_name ?: 'Unknown Item';
                }

                // Start with equipped item's values
                $actualOptLevel = (int)($item->equipped_opt_level ?? 0);
                $actualMagParamNum = (int)($item->equipped_mag_param_num ?? 0);
                $actualVariance = (int)($item->equipped_variance ?? 0);

                // ALWAYS try to find better instance using InventoryTooltipController logic
                $betterInstance = self::findActualItemInstance($item->ref_obj_id);

                if ($betterInstance) {
                    // Use better instance values if found (same logic as InventoryTooltipController)
                    $betterOptLevel = (int)($betterInstance['OptLevel'] ?? 0);
                    $betterMagParamNum = (int)($betterInstance['MagParamNum'] ?? 0);
                    $betterVariance = (int)($betterInstance['Variance'] ?? 0);

                    // Use the better values if they are superior
                    if ($betterOptLevel > $actualOptLevel || $betterMagParamNum > $actualMagParamNum || $betterVariance > $actualVariance) {
                        $actualOptLevel = $betterOptLevel;
                        $actualMagParamNum = $betterMagParamNum;
                        $actualVariance = $betterVariance;

                        Log::info("📈 InventoryHelper: Using enhanced data for slot {$item->slot} - OptLevel: {$actualOptLevel}, MagParam: {$actualMagParamNum}");
                    }
                }

                $processedEquipment[] = [
                    'slot' => $item->slot,
                    'item_id' => $item->item_id,
                    'name' => $displayName,
                    'code_name' => $item->code_name,
                    'icon_path' => $item->icon_path,
                    'rarity' => $item->rarity ?? 1,
                    'opt_level' => $actualOptLevel,
                    'mag_param_num' => $actualMagParamNum,
                    'variance' => $actualVariance,
                    'ref_item_id' => $item->ref_obj_id,
                    'ref_obj_id' => $item->ref_obj_id,
                    'RefItemID' => $item->ref_obj_id,
                    'name_str_id' => $item->name_str_id,
                    'desc_str_id' => $item->desc_str_id,
                    // Debug info
                    'debug_equipped_opt' => $item->equipped_opt_level,
                    'debug_actual_opt' => $actualOptLevel,
                    'debug_source' => $betterInstance ? $betterInstance['found_by'] : 'equipped_only'
                ];
            }

            Log::info("✅ InventoryHelper: Processed {$charId} equipment using InventoryTooltipController logic");
            return $processedEquipment;

        } catch (\Exception $e) {
            Log::error('Error fetching enhanced character equipment: ' . $e->getMessage(), [
                'char_id' => $charId,
                'trace' => $e->getTraceAsString()
            ]);
            return [];
        }
    }
}
