<?php

namespace App\Models\Warehouse;

use App\Models\User;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\MorphTo;

class StockMovement extends Model
{
    use HasFactory;

    protected $fillable = [
        'item_id',
        'movement_type',
        'reference_type',
        'reference_id',
        'quantity_before',
        'quantity_moved',
        'quantity_after',
        'division_id',
        'user_id',
        'notes'
    ];

    protected $casts = [
        'quantity_before' => 'decimal:2',
        'quantity_moved' => 'decimal:2',
        'quantity_after' => 'decimal:2',
        'movement_type' => 'string',
        'reference_type' => 'string',
        'created_at' => 'datetime',
        'updated_at' => 'datetime'
    ];

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

        static::creating(function ($movement) {
            // Auto-calculate quantity_after if not provided
            if ($movement->quantity_after === null) {
                $movement->quantity_after = match ($movement->movement_type) {
                    'in', 'return' => $movement->quantity_before + $movement->quantity_moved,
                    'out', 'adjustment' => $movement->quantity_before - $movement->quantity_moved,
                    'transfer' => $movement->quantity_before - $movement->quantity_moved,
                    default => $movement->quantity_before
                };
            }
        });
    }

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

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

    /**
     * Get the user who performed this movement
     */
    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class);
    }

    /**
     * Get the reference model (polymorphic relationship)
     */
    public function reference(): MorphTo
    {
        return $this->morphTo();
    }

    /**
     * Scope for incoming movements
     */
    public function scopeIncoming($query)
    {
        return $query->whereIn('movement_type', ['in', 'return']);
    }

    /**
     * Scope for outgoing movements
     */
    public function scopeOutgoing($query)
    {
        return $query->whereIn('movement_type', ['out', 'transfer']);
    }

    /**
     * Scope for adjustments
     */
    public function scopeAdjustments($query)
    {
        return $query->where('movement_type', 'adjustment');
    }

    /**
     * Scope for movements by date range
     */
    public function scopeDateBetween($query, $startDate, $endDate)
    {
        return $query->whereBetween('created_at', [$startDate, $endDate]);
    }

    /**
     * Scope for movements by item
     */
    public function scopeForItem($query, $itemId)
    {
        return $query->where('item_id', $itemId);
    }

    /**
     * Get movement type badge color for UI
     */
    public function getMovementTypeBadgeColorAttribute()
    {
        return match ($this->movement_type) {
            'in' => 'success',
            'out' => 'danger',
            'return' => 'info',
            'adjustment' => 'warning',
            'transfer' => 'primary',
            default => 'secondary'
        };
    }

    /**
     * Get movement type icon for UI
     */
    public function getMovementTypeIconAttribute()
    {
        return match ($this->movement_type) {
            'in' => 'fa-arrow-down',
            'out' => 'fa-arrow-up',
            'return' => 'fa-undo',
            'adjustment' => 'fa-edit',
            'transfer' => 'fa-exchange-alt',
            default => 'fa-question'
        };
    }

    /**
     * Get formatted movement description
     */
    public function getMovementDescriptionAttribute()
    {
        $description = ucfirst($this->movement_type) . ' movement';

        if ($this->reference_type) {
            $description .= " from {$this->reference_type}";
        }

        if ($this->notes) {
            $description .= " - {$this->notes}";
        }

        return $description;
    }

    /**
     * Check if movement increases stock
     */
    public function getIncreasesStockAttribute()
    {
        if ($this->movement_type === 'adjustment') {
            return $this->quantity_after > $this->quantity_before;
        }
        return in_array($this->movement_type, ['in', 'return', 'transfer_in']);
    }

    /**
     * Check if movement decreases stock
     */
    public function getDecreasesStockAttribute()
    {
        if ($this->movement_type === 'adjustment') {
            return $this->quantity_after < $this->quantity_before;
        }
        return in_array($this->movement_type, ['out', 'transfer', 'transfer_out']);
    }

    /**
     * Get the net quantity change
     */
    public function getNetQuantityChangeAttribute()
    {
        return $this->increases_stock
            ? $this->quantity_moved
            : -$this->quantity_moved;
    }
}