<?php

namespace App\Models\Warehouse;

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

class Inventory extends Model
{
    use HasFactory;

    protected $table = 'inventory';

    protected $fillable = [
        'item_id',
        'division_id',
        'supplier_id',
        'quantity_available',
        'unit_price',
        'purchase_price',
        'vat_amount',
        'currency',
        'total_value',
        'location',
        'batch_number',
        'supplier_batch_number',
        'purchase_order_number',
        'production_date',
        'expiry_date',
        'status',
        'delivery_status',
        'delivery_type',
        'delivery_reference',
        'delivered_at',
        'dispatched_at',
        'quality_status',
        'quality_notes',
        'compliance_verified',
        'last_updated'
    ];

    protected $casts = [
        'quantity_available' => 'decimal:2',
        'unit_price' => 'decimal:2',
        'purchase_price' => 'decimal:2',
        'vat_amount' => 'decimal:2',
        'total_value' => 'decimal:2',
        'production_date' => 'date',
        'expiry_date' => 'date',
        'status' => 'string',
        'delivery_status' => 'string',
        'quality_status' => 'string',
        'compliance_verified' => 'boolean',
        'delivered_at' => 'datetime',
        'dispatched_at' => 'datetime',
        'last_updated' => 'datetime',
        'created_at' => 'datetime',
        'updated_at' => 'datetime'
    ];

    /**
     * Boot the model
     */
    protected static function boot()
    {
        parent::boot();

        static::saving(function ($inventory) {
            // Auto-calculate total value
            $inventory->total_value = $inventory->quantity_available * $inventory->unit_price;

            // Update status based on quantity
            if ($inventory->quantity_available <= 0) {
                $inventory->status = 'out_of_stock';
            } elseif ($inventory->quantity_available <= ($inventory->item->reorder_point ?? 10)) {
                $inventory->status = 'low_stock';
            } else {
                $inventory->status = 'in_stock';
            }

            // Update last_updated timestamp
            $inventory->last_updated = now();
        });
    }

    /**
     * Get the item that owns the inventory
     */
    public function item(): BelongsTo
    {
        return $this->belongsTo(Item::class);
    }

    /**
     * Get the division that owns the inventory
     */
    public function division(): BelongsTo
    {
        return $this->belongsTo(ProjectDivision::class, 'division_id');
    }

    /**
     * Get the supplier for this inventory item
     */
    public function supplier(): BelongsTo
    {
        return $this->belongsTo(Supplier::class);
    }

    /**
     * Scope to get only in-stock inventory
     */
    public function scopeInStock($query)
    {
        return $query->where('status', 'in_stock');
    }

    /**
     * Scope to get low stock inventory
     */
    public function scopeLowStock($query)
    {
        return $query->where('status', 'low_stock');
    }

    /**
     * Scope to get out of stock inventory
     */
    public function scopeOutOfStock($query)
    {
        return $query->where('status', 'out_of_stock');
    }

    /**
     * Scope to get expired items
     */
    public function scopeExpired($query)
    {
        return $query->whereNotNull('expiry_date')
            ->where('expiry_date', '<', now());
    }

    /**
     * Scope to get items expiring soon (within 30 days)
     */
    public function scopeExpiringSoon($query, $days = 30)
    {
        return $query->whereNotNull('expiry_date')
            ->whereBetween('expiry_date', [now(), now()->addDays($days)]);
    }

    /**
     * Check if inventory item is expired
     */
    public function getIsExpiredAttribute()
    {
        return $this->expiry_date && $this->expiry_date < now();
    }

    /**
     * Check if inventory item is expiring soon
     */
    public function getIsExpiringSoonAttribute()
    {
        return $this->expiry_date &&
               $this->expiry_date > now() &&
               $this->expiry_date <= now()->addDays(30);
    }

    /**
     * Get days until expiry
     */
    public function getDaysUntilExpiryAttribute()
    {
        if (!$this->expiry_date) {
            return null;
        }

        return now()->diffInDays($this->expiry_date, false);
    }

    /**
     * Update quantity and recalculate values
     */
    public function updateQuantity($quantity, $operation = 'add')
    {
        if ($operation === 'add') {
            $this->quantity_available += $quantity;
        } else {
            $this->quantity_available = max(0, $this->quantity_available - $quantity);
        }

        $this->save();
    }
}