<?php

namespace App\Models\Warehouse;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;

class Item extends Model
{
    use HasFactory;

    protected $fillable = [
        'item_code',
        'item_description',
        'category_id',
        'item_type_id',
        'unit_id',
        'unit_of_measure',
        'min_stock_level',
        'max_stock_level',
        'reorder_point',
        'status',
        'notes'
    ];

    protected $casts = [
        'min_stock_level' => 'decimal:2',
        'max_stock_level' => 'decimal:2',
        'reorder_point' => 'decimal:2',
        'status' => 'string',
        'created_at' => 'datetime',
        'updated_at' => 'datetime'
    ];

    /**
     * Get the category that owns the item
     */
    public function category(): BelongsTo
    {
        return $this->belongsTo(ItemCategory::class, 'category_id');
    }

    /**
     * Get the item type that owns the item
     */
    public function itemType(): BelongsTo
    {
        return $this->belongsTo(ItemType::class, 'item_type_id');
    }

    /**
     * Get the unit that owns the item
     */
    public function unit(): BelongsTo
    {
        return $this->belongsTo(Unit::class, 'unit_id');
    }

    /**
     * Get all inventory records for the item
     */
    public function inventories(): HasMany
    {
        return $this->hasMany(Inventory::class);
    }

    /**
     * Get all incoming item records
     */
    public function incomingItems(): HasMany
    {
        return $this->hasMany(IncomingItem::class);
    }

    /**
     * Get all outgoing item records
     */
    public function outgoingItems(): HasMany
    {
        return $this->hasMany(OutgoingItem::class);
    }

    /**
     * Get all return item records
     */
    public function returnItems(): HasMany
    {
        return $this->hasMany(ReturnItem::class);
    }

    /**
     * Get all stock movements for the item
     */
    public function stockMovements(): HasMany
    {
        return $this->hasMany(StockMovement::class);
    }

    /**
     * Scope to get only active items
     */
    public function scopeActive($query)
    {
        return $query->where('status', 'active');
    }

    /**
     * Scope for searching items by code, description, or category name
     */
    public function scopeSearch($query, $search)
    {
        if (empty($search)) {
            return $query;
        }

        return $query->where(function ($q) use ($search) {
            $q->where('item_code', 'LIKE', "%{$search}%")
              ->orWhere('item_description', 'LIKE', "%{$search}%")
              ->orWhere('notes', 'LIKE', "%{$search}%")
              ->orWhereHas('category', function ($q) use ($search) {
                  $q->where('category_name', 'LIKE', "%{$search}%");
              });
        });
    }

    /**
     * Scope to get items that need reordering
     */
    public function scopeNeedsReorder($query)
    {
        return $query->whereHas('inventories', function ($q) {
            $q->selectRaw('item_id, SUM(quantity_available) as total_quantity')
                ->groupBy('item_id')
                ->havingRaw('total_quantity <= items.reorder_point');
        });
    }

    /**
     * Get total quantity available across all locations
     */
    public function getTotalQuantityAttribute()
    {
        return $this->inventories()->sum('quantity_available');
    }

    /**
     * Get average unit price from inventory
     */
    public function getAverageUnitPriceAttribute()
    {
        $inventory = $this->inventories()
            ->where('quantity_available', '>', 0)
            ->select('unit_price', 'quantity_available')
            ->get();

        if ($inventory->isEmpty()) {
            return 0;
        }

        $totalValue = $inventory->sum(function ($item) {
            return $item->unit_price * $item->quantity_available;
        });

        $totalQuantity = $inventory->sum('quantity_available');

        return $totalQuantity > 0 ? $totalValue / $totalQuantity : 0;
    }

    /**
     * Check if item is below reorder point
     */
    public function getBelowReorderPointAttribute()
    {
        return $this->total_quantity <= $this->reorder_point;
    }

    /**
     * Check if item is out of stock
     */
    public function getIsOutOfStockAttribute()
    {
        return $this->total_quantity <= 0;
    }

    /**
     * Get the latest stock movement
     */
    public function latestStockMovement()
    {
        return $this->hasOne(StockMovement::class)->latest();
    }
}