<?php

namespace App\Models;

use App\Models\Traits\HasAuditFields;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;

class SkuMovement extends Model
{
    use SoftDeletes, HasAuditFields;

    protected $table = 'sku_movements';

    /**
     * Movement type constants
     */
    public const TYPE_INBOUND = 'inbound';
    public const TYPE_OUTBOUND = 'outbound';
    public const TYPE_TRANSFER = 'transfer';
    public const TYPE_ADJUSTMENT = 'adjustment';

    /**
     * Status constants
     */
    public const STATUS_PENDING = 'pending';
    public const STATUS_IN_TRANSIT = 'in_transit';
    public const STATUS_COMPLETED = 'completed';
    public const STATUS_CANCELLED = 'cancelled';

    protected $fillable = [
        'reference',
        'sku_id',
        'product',
        'type',
        'quantity',
        'from_location',
        'to_location',
        'date',
        'status',
        'notes',
        'created_by',
        'updated_by',
    ];

    protected $casts = [
        'date' => 'date',
        'quantity' => 'decimal:2',
        'created_at' => 'datetime',
        'updated_at' => 'datetime',
    ];

    // ──────────────────────────────────────────────────────────────────────────
    // RELATIONSHIPS
    // ──────────────────────────────────────────────────────────────────────────

    /**
     * Get the SKU this movement belongs to.
     */
    public function sku()
    {
        return $this->belongsTo(SkuMaster::class, 'sku_id');
    }

    /**
     * Get the user who created this movement.
     */
    public function creator()
    {
        return $this->belongsTo(User::class, 'created_by');
    }

    // ──────────────────────────────────────────────────────────────────────────
    // SCOPES
    // ──────────────────────────────────────────────────────────────────────────

    /**
     * Filter by inbound type
     */
    public function scopeInbound(Builder $query): Builder
    {
        return $query->where('type', self::TYPE_INBOUND);
    }

    /**
     * Filter by outbound type
     */
    public function scopeOutbound(Builder $query): Builder
    {
        return $query->where('type', self::TYPE_OUTBOUND);
    }

    /**
     * Filter by transfer type
     */
    public function scopeTransfer(Builder $query): Builder
    {
        return $query->where('type', self::TYPE_TRANSFER);
    }

    /**
     * Filter by adjustment type
     */
    public function scopeAdjustment(Builder $query): Builder
    {
        return $query->where('type', self::TYPE_ADJUSTMENT);
    }

    /**
     * Filter by pending status
     */
    public function scopePending(Builder $query): Builder
    {
        return $query->where('status', self::STATUS_PENDING);
    }

    /**
     * Filter by completed status
     */
    public function scopeCompleted(Builder $query): Builder
    {
        return $query->where('status', self::STATUS_COMPLETED);
    }

    /**
     * Filter by SKU
     */
    public function scopeForSku(Builder $query, int $skuId): Builder
    {
        return $query->where('sku_id', $skuId);
    }

    /**
     * Filter by date range
     */
    public function scopeBetweenDates(Builder $query, $startDate, $endDate): Builder
    {
        return $query->whereBetween('date', [$startDate, $endDate]);
    }

    /**
     * Filter by location (from or to)
     */
    public function scopeAtLocation(Builder $query, string $location): Builder
    {
        return $query->where(function ($q) use ($location) {
            $q->where('from_location', $location)
              ->orWhere('to_location', $location);
        });
    }

    /**
     * Filter recent movements
     */
    public function scopeRecent(Builder $query, int $days = 30): Builder
    {
        return $query->where('date', '>=', now()->subDays($days));
    }

    // ──────────────────────────────────────────────────────────────────────────
    // ACCESSORS & HELPERS
    // ──────────────────────────────────────────────────────────────────────────

    /**
     * Get all valid types
     */
    public static function getTypes(): array
    {
        return [
            self::TYPE_INBOUND,
            self::TYPE_OUTBOUND,
            self::TYPE_TRANSFER,
            self::TYPE_ADJUSTMENT,
        ];
    }

    /**
     * Get all valid statuses
     */
    public static function getStatuses(): array
    {
        return [
            self::STATUS_PENDING,
            self::STATUS_IN_TRANSIT,
            self::STATUS_COMPLETED,
            self::STATUS_CANCELLED,
        ];
    }

    /**
     * Get type label
     */
    public function getTypeLabel(): string
    {
        return match($this->type) {
            self::TYPE_INBOUND => 'Inbound',
            self::TYPE_OUTBOUND => 'Outbound',
            self::TYPE_TRANSFER => 'Transfer',
            self::TYPE_ADJUSTMENT => 'Adjustment',
            default => ucfirst($this->type ?? 'Unknown'),
        };
    }

    /**
     * Get status label
     */
    public function getStatusLabel(): string
    {
        return match($this->status) {
            self::STATUS_PENDING => 'Pending',
            self::STATUS_IN_TRANSIT => 'In Transit',
            self::STATUS_COMPLETED => 'Completed',
            self::STATUS_CANCELLED => 'Cancelled',
            default => ucfirst($this->status ?? 'Unknown'),
        };
    }

    /**
     * Check if movement is inbound
     */
    public function isInbound(): bool
    {
        return $this->type === self::TYPE_INBOUND;
    }

    /**
     * Check if movement is outbound
     */
    public function isOutbound(): bool
    {
        return $this->type === self::TYPE_OUTBOUND;
    }

    /**
     * Check if movement is completed
     */
    public function isCompleted(): bool
    {
        return $this->status === self::STATUS_COMPLETED;
    }

    /**
     * Check if movement is pending
     */
    public function isPending(): bool
    {
        return $this->status === self::STATUS_PENDING;
    }

    /**
     * Get signed quantity (positive for inbound, negative for outbound)
     */
    public function getSignedQuantity(): float
    {
        return $this->isOutbound() ? -$this->quantity : $this->quantity;
    }
}
