<?php

namespace App\Models\SRO_VT_SHARD;

use Illuminate\Database\Eloquent\Model;
use App\Models\SRO_VT_SHARD\RefObjItem;
use App\Models\SRO_VT_SHARD\Items;
use App\Models\SRO_VT_SHARD\RefObjChar;
use App\Helpers\TextDataHelper;
use Illuminate\Support\Facades\Log;

class RefObjCommon extends Model
{
    /**
     * The Database connection name for the model.
     *
     * @var string
     */
    protected $connection = 'sqlsrv_shard';

    /**
     * Indicates if the model should be timestamped.
     *
     * @var bool
     */
    public $timestamps = false;

    /**
     * The table associated with the model.
     *
     * @var string
     */
    protected $table = 'dbo._RefObjCommon';

    /**
     * The primary key associated with the table.
     *
     * @var string
     */
    protected $primaryKey = 'ID';

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'Service',
        'CodeName128',
        'ObjName128',
        'OrgObjCodeName128',
        'NameStrID128',
        'DescStrID128',
        'CashItem',
        'Bionic',
        'TypeID1',
        'TypeID2',
        'TypeID3',
        'TypeID4',
        'DecayTime',
        'Country',
        'Rarity',
        'CanTrade',
        'CanSell',
        'CanBuy',
        'CanBorrow',
        'CanDrop',
        'CanPick',
        'CanRepair',
        'CanRevive',
        'CanUse',
        'CanThrow',
        'Price',
        'CostRepair',
        'CostRevive',
        'CostBorrow',
        'KeepingFee',
        'SellPrice',
        'ReqLevelType1',
        'ReqLevel1',
        'ReqLevelType2',
        'ReqLevel2',
        'ReqLevelType3',
        'ReqLevel3',
        'ReqLevelType4',
        'ReqLevel4',
        'MaxContain',
        'RegionID',
        'Dir',
        'OffsetX',
        'OffsetY',
        'OffsetZ',
        'Speed1',
        'Speed2',
        'Scale',
        'BCHeight',
        'BCRadius',
        'EventID',
        'AssocFileObj128',
        'AssocFileDrop128',
        'AssocFileIcon128',
        'AssocFile1_128',
        'AssocFile2_128',
        'Link'
    ];

    /**
     * The attributes that should be casted to native types.
     *
     * @var array
     */
    protected $casts = [
        // Basic info
        'Service' => 'integer',
        'ID' => 'integer',
        'CodeName128' => 'string',
        'ObjName128' => 'string',
        'OrgObjCodeName128' => 'string',
        'NameStrID128' => 'string',
        'DescStrID128' => 'string',

        // Item properties
        'CashItem' => 'integer',
        'Bionic' => 'integer',
        'TypeID1' => 'integer',
        'TypeID2' => 'integer',
        'TypeID3' => 'integer',
        'TypeID4' => 'integer',
        'DecayTime' => 'integer',
        'Country' => 'integer',
        'Rarity' => 'integer',

        // Permissions
        'CanTrade' => 'integer',
        'CanSell' => 'integer',
        'CanBuy' => 'integer',
        'CanBorrow' => 'integer',
        'CanDrop' => 'integer',
        'CanPick' => 'integer',
        'CanRepair' => 'integer',
        'CanRevive' => 'integer',
        'CanUse' => 'integer',
        'CanThrow' => 'integer',

        // Costs and prices
        'Price' => 'integer',
        'CostRepair' => 'integer',
        'CostRevive' => 'integer',
        'CostBorrow' => 'integer',
        'KeepingFee' => 'integer',
        'SellPrice' => 'integer',

        // Requirements
        'ReqLevelType1' => 'integer',
        'ReqLevel1' => 'integer',
        'ReqLevelType2' => 'integer',
        'ReqLevel2' => 'integer',
        'ReqLevelType3' => 'integer',
        'ReqLevel3' => 'integer',
        'ReqLevelType4' => 'integer',
        'ReqLevel4' => 'integer',
        'MaxContain' => 'integer',

        // Position and physics
        'RegionID' => 'integer',
        'Dir' => 'integer',
        'OffsetX' => 'integer',
        'OffsetY' => 'integer',
        'OffsetZ' => 'integer',
        'Speed1' => 'integer',
        'Speed2' => 'integer',
        'Scale' => 'integer',
        'BCHeight' => 'integer',
        'BCRadius' => 'integer',
        'EventID' => 'integer',

        // File associations
        'AssocFileObj128' => 'string',
        'AssocFileDrop128' => 'string',
        'AssocFileIcon128' => 'string',
        'AssocFile1_128' => 'string',
        'AssocFile2_128' => 'string',

        // Links
        'Link' => 'integer',
    ];

    // =========================================================================
    // RELATIONSHIPS
    // =========================================================================

    /**
     * Get all items that reference this object definition
     * ID -> Items.RefItemID
     *
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function items()
    {
        return $this->hasMany(Items::class, 'RefItemID', 'ID');
    }

    /**
     * Get the detailed item information (if this is an item)
     * Link -> RefObjItem.ID
     *
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function refObjItem()
    {
        return $this->belongsTo(RefObjItem::class, 'Link', 'ID');
    }

    /**
     * Get the detailed character information (if this is a character/NPC)
     * Link -> RefObjChar.ID
     *
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function refObjChar()
    {
        return $this->belongsTo(RefObjChar::class, 'Link', 'ID');
    }    // =========================================================================
    // DEPRECATED METHODS (keeping for backward compatibility)
    // =========================================================================

    /**
     * @deprecated Use refObjItem() instead
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function getRefObjItem()
    {
        return $this->refObjItem();
    }

    // =========================================================================
    // HELPER METHODS
    // =========================================================================

    /**
     * Check if item is a cash item
     *
     * @return bool
     */
    public function isCashItem()
    {
        return $this->CashItem == 1;
    }

    /**
     * Check if item is bionic
     *
     * @return bool
     */
    public function isBionic()
    {
        return $this->Bionic == 1;
    }

    /**
     * Check if item can be traded
     *
     * @return bool
     */
    public function canTrade()
    {
        return $this->CanTrade == 1;
    }

    /**
     * Check if item can be sold
     *
     * @return bool
     */
    public function canSell()
    {
        return $this->CanSell == 1;
    }

    /**
     * Check if item can be dropped
     *
     * @return bool
     */
    public function canDrop()
    {
        return $this->CanDrop == 1;
    }

    /**
     * Get item type as array
     *
     * @return array
     */
    public function getItemType()
    {
        return [
            'type1' => $this->TypeID1,
            'type2' => $this->TypeID2,
            'type3' => $this->TypeID3,
            'type4' => $this->TypeID4,
        ];
    }

    /**
     * Get rarity name
     *
     * @return string
     */
    public function getRarityName()
    {
        $rarities = [
            1 => 'Normal',
            2 => 'Rare',
            3 => 'Epic',
            4 => 'Legendary',
            5 => 'Mythic'
        ];

        return $rarities[$this->Rarity] ?? 'Unknown';
    }

    /**
     * Get all requirements as array
     *
     * @return array
     */
    public function getRequirements()
    {
        $requirements = [];

        for ($i = 1; $i <= 4; $i++) {
            $typeField = "ReqLevelType{$i}";
            $levelField = "ReqLevel{$i}";

            if ($this->{$typeField} > 0 && $this->{$levelField} > 0) {
                $requirements[] = [
                    'type' => $this->{$typeField},
                    'level' => $this->{$levelField}
                ];
            }
        }

        return $requirements;
    }

    /**
     * Get icon path for web display
     *
     * @return string
     */
    public function getIconPath()
    {
        if (!$this->AssocFileIcon128) {
            return '/assets/images/ui/placeholder-item.svg';
        }

        // Convert .ddj to .jpg and add web path
        $iconPath = str_replace('.ddj', '.jpg', $this->AssocFileIcon128);
        return '/assets/images/sro/' . str_replace('\\', '/', $iconPath);
    }

    // =========================================================================
    // TEXTDATA INTEGRATION METHODS
    // =========================================================================

    /**
     * Get localized item name from textdata files
     * Uses NameStrID128 to lookup in textdata_*.txt files
     *
     * @return string|null
     */
    public function getLocalizedName()
    {
        try {
            if (empty($this->NameStrID128)) {
                return null;
            }
            return TextDataHelper::getText($this->NameStrID128);
        } catch (\Exception $e) {
            Log::warning("Failed to get localized name for {$this->NameStrID128}: " . $e->getMessage());
            return null;
        }
    }

    /**
     * Get localized item description from textdata files
     * Uses DescStrID128 to lookup in textdata_*.txt files
     *
     * @return string|null
     */
    public function getLocalizedDescription()
    {
        try {
            if (empty($this->DescStrID128)) {
                return null;
            }
            return TextDataHelper::getText($this->DescStrID128);
        } catch (\Exception $e) {
            Log::warning("Failed to get localized description for {$this->DescStrID128}: " . $e->getMessage());
            return null;
        }
    }

    /**
     * Get the best available name (localized or fallback)
     * Tries: Localized Name -> ObjName128 -> CodeName128
     *
     * @return string
     */
    public function getDisplayName()
    {
        // Try localized name first
        $localizedName = $this->getLocalizedName();
        if (!empty($localizedName)) {
            return $localizedName;
        }

        // Fallback to ObjName128
        if (!empty($this->ObjName128)) {
            return $this->ObjName128;
        }

        // Final fallback to CodeName128
        return $this->CodeName128 ?? 'Unknown Item';
    }

    /**
     * Get complete item information including localized text
     *
     * @return array
     */
    public function getCompleteInfo()
    {
        try {
            return [
                // Basic identifiers
                'id' => $this->ID,
                'code_name' => $this->CodeName128,
                'obj_name' => $this->ObjName128,

                // Localized text
                'name_str_id' => $this->NameStrID128,
                'desc_str_id' => $this->DescStrID128,
                'localized_name' => $this->getLocalizedName(),
                'localized_description' => $this->getLocalizedDescription(),
                'display_name' => $this->getDisplayName(),

                // Item properties
                'rarity' => $this->Rarity,
                'rarity_name' => $this->getRarityName(),
                'type' => $this->getItemType(),
                'requirements' => $this->getRequirements(),

                // Files and assets
                'icon_path' => $this->getIconPath(),
                'original_icon' => $this->AssocFileIcon128,

                // Trading properties
                'can_trade' => $this->canTrade(),
                'can_sell' => $this->canSell(),
                'can_drop' => $this->canDrop(),
                'price' => $this->Price,

                // Flags
                'is_cash_item' => $this->isCashItem(),
                'is_bionic' => $this->isBionic(),
            ];
        } catch (\Exception $e) {
            Log::error("Error in getCompleteInfo for item {$this->ID}: " . $e->getMessage());

            // Return minimal safe data
            return [
                'id' => $this->ID,
                'code_name' => $this->CodeName128 ?? 'Unknown',
                'obj_name' => $this->ObjName128 ?? 'Unknown',
                'display_name' => $this->ObjName128 ?? $this->CodeName128 ?? 'Unknown Item',
                'rarity' => $this->Rarity ?? 1,
                'rarity_name' => 'Normal',
                'icon_path' => '/assets/images/ui/placeholder-item.svg',
                'error' => 'Error loading complete info'
            ];
        }
    }

    // =========================================================================
    // SCOPES
    // =========================================================================

    /**
     * Scope to get only tradeable items
     *
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeTradeable($query)
    {
        return $query->where('CanTrade', 1);
    }

    /**
     * Scope to get only cash items
     *
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeCashItems($query)
    {
        return $query->where('CashItem', 1);
    }

    /**
     * Scope to get items by rarity
     *
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @param int $rarity
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeByRarity($query, $rarity)
    {
        return $query->where('Rarity', $rarity);
    }

    /**
     * Scope to get items by type
     *
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @param int $type1
     * @param int|null $type2
     * @param int|null $type3
     * @param int|null $type4
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeByType($query, $type1, $type2 = null, $type3 = null, $type4 = null)
    {
        $query->where('TypeID1', $type1);

        if (!is_null($type2)) $query->where('TypeID2', $type2);
        if (!is_null($type3)) $query->where('TypeID3', $type3);
        if (!is_null($type4)) $query->where('TypeID4', $type4);

        return $query;
    }

    //Get MaxStack from RefObjItem by send ID
    public static function getMaxStack($id)
    {
        $refObjItem = RefObjItem::where('ID', $id)->first();
        if ($refObjItem) {
            return $refObjItem->MaxStack;
        }

        return null;
    }

    //Get Sum MaxStack from RefObjItem by send array ID
    public static function getSumMaxStack($ids)
    {
        $sum = 0;
        foreach ($ids as $id) {
            $maxStack = self::getMaxStack($id);
            if ($maxStack) {
                $sum += $maxStack;
            }
        }

        return $sum;
    }
}
