<?php

namespace App\Models\SRO_VT_SHARD;

use Illuminate\Database\Eloquent\Model;
use App\Models\SRO_VT_SHARD\RefObjCommon;

class RefObjItem 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._RefObjItem';

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'MaxStack',
        'ReqGender',
        'ReqStr',
        'ReqInt',
        'ItemClass',
        'SetID',
        'Dur_L',
        'Dur_U',
        'PD_L',
        'PD_U',
        'PDInc',
        'ER_L',
        'ER_U',
        'ERInc',
        'PAR_L',
        'PAR_U',
        'PARInc',
        'BR_L',
        'BR_U',
        'MD_L',
        'MD_U',
        'MDInc',
        'MAR_L',
        'MAR_U',
        'MARInc',
        'PDStr_L',
        'PDStr_U',
        'MDInt_L',
        'MDInt_U',
        'Quivered',
        'Ammo1_TID4',
        'Ammo2_TID4',
        'Ammo3_TID4',
        'Ammo4_TID4',
        'Ammo5_TID4',
        'SpeedClass',
        'TwoHanded',
        'Range',
        'PAttackMin_L',
        'PAttackMin_U',
        'PAttackMax_L',
        'PAttackMax_U',
        'PAttackInc',
        'MAttackMin_L',
        'MAttackMin_U',
        'MAttackMax_L',
        'MAttackMax_U',
        'MAttackInc',
        'PAStrMin_L',
        'PAStrMin_U',
        'PAStrMax_L',
        'PAStrMax_U',
        'MAInt_Min_L',
        'MAInt_Min_U',
        'MAInt_Max_L',
        'MAInt_Max_U',
        'HR_L',
        'HR_U',
        'HRInc',
        'CHR_L',
        'CHR_U',
        'Param1',
        'Desc1_128',
        'Param2',
        'Desc2_128',
        'Param3',
        'Desc3_128',
        'Param4',
        'Desc4_128',
        'Param5',
        'Desc5_128',
        'Param6',
        'Desc6_128',
        'Param7',
        'Desc7_128',
        'Param8',
        'Desc8_128',
        'Param9',
        'Desc9_128',
        'Param10',
        'Desc10_128',
        'Param11',
        'Desc11_128',
        'Param12',
        'Desc12_128',
        'Param13',
        'Desc13_128',
        'Param14',
        'Desc14_128',
        'Param15',
        'Desc15_128',
        'Param16',
        'Desc16_128',
        'Param17',
        'Desc17_128',
        'Param18',
        'Desc18_128',
        'Param19',
        'Desc19_128',
        'Param20',
        'Desc20_128',
        'MaxMagicOptCount',
        'ChildItemCount'
    ];

    /**
     * The attributes that should be casted to native types.
     *
     * @var array
     */
    protected $casts = [
        // Basic properties
        'ID' => 'integer',
        'MaxStack' => 'integer',
        'ReqGender' => 'integer',
        'ReqStr' => 'integer',
        'ReqInt' => 'integer',
        'ItemClass' => 'integer',
        'SetID' => 'integer',

        // Durability (real/float)
        'Dur_L' => 'float',
        'Dur_U' => 'float',

        // Physical Defense (real/float)
        'PD_L' => 'float',
        'PD_U' => 'float',
        'PDInc' => 'float',

        // Evade Rate (real/float)
        'ER_L' => 'float',
        'ER_U' => 'float',
        'ERInc' => 'float',

        // Physical Attack Rate (real/float)
        'PAR_L' => 'float',
        'PAR_U' => 'float',
        'PARInc' => 'float',

        // Block Rate (real/float)
        'BR_L' => 'float',
        'BR_U' => 'float',

        // Magic Defense (real/float)
        'MD_L' => 'float',
        'MD_U' => 'float',
        'MDInc' => 'float',

        // Magic Attack Rate (real/float)
        'MAR_L' => 'float',
        'MAR_U' => 'float',
        'MARInc' => 'float',

        // STR/INT based stats (real/float)
        'PDStr_L' => 'float',
        'PDStr_U' => 'float',
        'MDInt_L' => 'float',
        'MDInt_U' => 'float',

        // Weapon properties
        'Quivered' => 'integer',
        'Ammo1_TID4' => 'integer',
        'Ammo2_TID4' => 'integer',
        'Ammo3_TID4' => 'integer',
        'Ammo4_TID4' => 'integer',
        'Ammo5_TID4' => 'integer',
        'SpeedClass' => 'integer',
        'TwoHanded' => 'integer',
        'Range' => 'integer',

        // Physical Attack (real/float)
        'PAttackMin_L' => 'float',
        'PAttackMin_U' => 'float',
        'PAttackMax_L' => 'float',
        'PAttackMax_U' => 'float',
        'PAttackInc' => 'float',

        // Magic Attack (real/float)
        'MAttackMin_L' => 'float',
        'MAttackMin_U' => 'float',
        'MAttackMax_L' => 'float',
        'MAttackMax_U' => 'float',
        'MAttackInc' => 'float',

        // STR based Physical Attack (real/float)
        'PAStrMin_L' => 'float',
        'PAStrMin_U' => 'float',
        'PAStrMax_L' => 'float',
        'PAStrMax_U' => 'float',

        // INT based Magic Attack (real/float)
        'MAInt_Min_L' => 'float',
        'MAInt_Min_U' => 'float',
        'MAInt_Max_L' => 'float',
        'MAInt_Max_U' => 'float',

        // Hit Rate and Critical Hit Rate (real/float)
        'HR_L' => 'float',
        'HR_U' => 'float',
        'HRInc' => 'float',
        'CHR_L' => 'float',
        'CHR_U' => 'float',

        // Parameters and descriptions
        'Param1' => 'integer',
        'Desc1_128' => 'string',
        'Param2' => 'integer',
        'Desc2_128' => 'string',
        'Param3' => 'integer',
        'Desc3_128' => 'string',
        'Param4' => 'integer',
        'Desc4_128' => 'string',
        'Param5' => 'integer',
        'Desc5_128' => 'string',
        'Param6' => 'integer',
        'Desc6_128' => 'string',
        'Param7' => 'integer',
        'Desc7_128' => 'string',
        'Param8' => 'integer',
        'Desc8_128' => 'string',
        'Param9' => 'integer',
        'Desc9_128' => 'string',
        'Param10' => 'integer',
        'Desc10_128' => 'string',
        'Param11' => 'integer',
        'Desc11_128' => 'string',
        'Param12' => 'integer',
        'Desc12_128' => 'string',
        'Param13' => 'integer',
        'Desc13_128' => 'string',
        'Param14' => 'integer',
        'Desc14_128' => 'string',
        'Param15' => 'integer',
        'Desc15_128' => 'string',
        'Param16' => 'integer',
        'Desc16_128' => 'string',
        'Param17' => 'integer',
        'Desc17_128' => 'string',
        'Param18' => 'integer',
        'Desc18_128' => 'string',
        'Param19' => 'integer',
        'Desc19_128' => 'string',
        'Param20' => 'integer',
        'Desc20_128' => 'string',

        // Magic options and child items
        'MaxMagicOptCount' => 'integer',
        'ChildItemCount' => 'integer',
    ];

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

    /**
     * Get the common object definition for this item
     * ID -> RefObjCommon.Link
     *
     * @return \Illuminate\Database\Eloquent\Relations\HasOne
     */
    public function refObjCommon()
    {
        return $this->hasOne(RefObjCommon::class, 'Link', 'ID');
    }

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

    /**
     * Check if item is stackable
     *
     * @return bool
     */
    public function isStackable()
    {
        return $this->MaxStack > 1;
    }

    /**
     * Check if item is two-handed
     *
     * @return bool
     */
    public function isTwoHanded()
    {
        return $this->TwoHanded == 1;
    }

    /**
     * Check if item has quiver (for arrows/bolts)
     *
     * @return bool
     */
    public function hasQuiver()
    {
        return $this->Quivered == 1;
    }

    /**
     * Get gender requirement name
     *
     * @return string
     */
    public function getGenderRequirement()
    {
        switch ($this->ReqGender) {
            case 0:
                return 'Any';
            case 1:
                return 'Male';
            case 2:
                return 'Female';
            default:
                return 'Unknown';
        }
    }

    /**
     * Get physical defense range
     *
     * @return array
     */
    public function getPhysicalDefenseRange()
    {
        return [
            'min' => $this->PD_L,
            'max' => $this->PD_U,
            'increment' => $this->PDInc
        ];
    }

    /**
     * Get magic defense range
     *
     * @return array
     */
    public function getMagicDefenseRange()
    {
        return [
            'min' => $this->MD_L,
            'max' => $this->MD_U,
            'increment' => $this->MDInc
        ];
    }

    /**
     * Get physical attack range
     *
     * @return array
     */
    public function getPhysicalAttackRange()
    {
        return [
            'min_low' => $this->PAttackMin_L,
            'min_high' => $this->PAttackMin_U,
            'max_low' => $this->PAttackMax_L,
            'max_high' => $this->PAttackMax_U,
            'increment' => $this->PAttackInc
        ];
    }

    /**
     * Get magic attack range
     *
     * @return array
     */
    public function getMagicAttackRange()
    {
        return [
            'min_low' => $this->MAttackMin_L,
            'min_high' => $this->MAttackMin_U,
            'max_low' => $this->MAttackMax_L,
            'max_high' => $this->MAttackMax_U,
            'increment' => $this->MAttackInc
        ];
    }

    /**
     * Get durability range
     *
     * @return array
     */
    public function getDurabilityRange()
    {
        return [
            'min' => $this->Dur_L,
            'max' => $this->Dur_U
        ];
    }

    /**
     * Get hit rate range
     *
     * @return array
     */
    public function getHitRateRange()
    {
        return [
            'min' => $this->HR_L,
            'max' => $this->HR_U,
            'increment' => $this->HRInc
        ];
    }

    /**
     * Get critical hit rate range
     *
     * @return array
     */
    public function getCriticalHitRateRange()
    {
        return [
            'min' => $this->CHR_L,
            'max' => $this->CHR_U
        ];
    }

    /**
     * Get compatible ammo types
     *
     * @return array
     */
    public function getCompatibleAmmoTypes()
    {
        $ammoTypes = [];
        for ($i = 1; $i <= 5; $i++) {
            $ammoField = "Ammo{$i}_TID4";
            if ($this->{$ammoField} > 0) {
                $ammoTypes[] = $this->{$ammoField};
            }
        }
        return $ammoTypes;
    }

    /**
     * Get all parameters and descriptions
     *
     * @return array
     */
    public function getParametersAndDescriptions()
    {
        $params = [];
        for ($i = 1; $i <= 20; $i++) {
            $paramField = "Param{$i}";
            $descField = "Desc{$i}_128";

            if ($this->{$paramField} != 0 || !empty($this->{$descField})) {
                $params[] = [
                    'param' => $this->{$paramField},
                    'description' => $this->{$descField}
                ];
            }
        }
        return $params;
    }

    /**
     * Get requirements as array
     *
     * @return array
     */
    public function getRequirements()
    {
        return [
            'gender' => $this->getGenderRequirement(),
            'strength' => $this->ReqStr,
            'intelligence' => $this->ReqInt
        ];
    }

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

    /**
     * Scope to get items by item class
     *
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @param int $itemClass
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeByItemClass($query, $itemClass)
    {
        return $query->where('ItemClass', $itemClass);
    }

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

    /**
     * Scope to get two-handed items
     *
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeTwoHanded($query)
    {
        return $query->where('TwoHanded', 1);
    }

    /**
     * Scope to get items with magic options
     *
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeWithMagicOptions($query)
    {
        return $query->where('MaxMagicOptCount', '>', 0);
    }

    /**
     * Scope to get items by minimum strength requirement
     *
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @param int $minStr
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeMinStrength($query, $minStr)
    {
        return $query->where('ReqStr', '>=', $minStr);
    }

    /**
     * Scope to get items by minimum intelligence requirement
     *
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @param int $minInt
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeMinIntelligence($query, $minInt)
    {
        return $query->where('ReqInt', '>=', $minInt);
    }
}
