<?php

namespace App\Models;

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

class MenuItem extends Model
{
    use HasFactory;

    protected $fillable = [
        'restaurant_id',
        'category_id',
        'name',
        'slug',
        'description',
        'price',
        'image',
        'sku',
        'has_variants',
        'track_inventory',
        'stock_quantity',
        'low_stock_alert',
        'kitchen_stations',
        'prep_time',
        'is_available',
        'is_active',
    ];

    protected $casts = [
        'price' => 'decimal:2',
        'has_variants' => 'boolean',
        'track_inventory' => 'boolean',
        'kitchen_stations' => 'array',
        'is_available' => 'boolean',
        'is_active' => 'boolean',
    ];

    public function restaurant(): BelongsTo
    {
        return $this->belongsTo(Restaurant::class);
    }

    public function category(): BelongsTo
    {
        return $this->belongsTo(Category::class);
    }

    public function orderItems(): HasMany
    {
        return $this->hasMany(OrderItem::class);
    }

    public function ingredients(): BelongsToMany
    {
        return $this->belongsToMany(InventoryItem::class, 'menu_item_ingredients')
            ->withPivot('quantity_required', 'unit')
            ->withTimestamps();
    }

    public function getImageUrlAttribute(): ?string
    {
        if (!$this->image) {
            return null;
        }

        // Return full URL if it's already a URL, otherwise prepend storage path
        if (str_starts_with($this->image, 'http')) {
            return $this->image;
        }

        // Use Laravel's Storage facade with the corrected filesystem configuration
        return \Illuminate\Support\Facades\Storage::disk('public')->url($this->image);
    }

    public function getFormattedPriceAttribute(): string
    {
        return 'KES ' . number_format($this->price, 2);
    }

    public function getKitchenStationsDisplayAttribute(): string
    {
        if (!$this->kitchen_stations) {
            return 'Main Kitchen';
        }

        return collect($this->kitchen_stations)
            ->map(fn($station) => ucfirst($station))
            ->implode(', ');
    }

    public function getPrepTimeDisplayAttribute(): ?string
    {
        if (!$this->prep_time) {
            return null;
        }

        return $this->prep_time . ' min' . ($this->prep_time > 1 ? 's' : '');
    }

    public function isInStock(): bool
    {
        if (!$this->track_inventory) {
            return true;
        }

        return $this->stock_quantity > 0;
    }

    public function isLowStock(): bool
    {
        if (!$this->track_inventory || !$this->low_stock_alert) {
            return false;
        }

        return $this->stock_quantity <= $this->low_stock_alert;
    }

    public function canBeOrdered(): bool
    {
        return $this->is_active && $this->is_available && $this->isInStock();
    }

    public function adjustStock(int $quantity, string $reference = null): void
    {
        if (!$this->track_inventory) {
            return;
        }

        $newQuantity = max(0, $this->stock_quantity + $quantity);
        $this->update(['stock_quantity' => $newQuantity]);

        // Also adjust ingredient stock if configured
        foreach ($this->ingredients as $ingredient) {
            $requiredQuantity = $ingredient->pivot->quantity_required * abs($quantity);
            if ($quantity < 0) { // Stock out (sale)
                $ingredient->adjustStock(-$requiredQuantity, 'sale', $reference);
            }
        }
    }

    public function checkIngredientAvailability(): array
    {
        $unavailable = [];
        
        foreach ($this->ingredients as $ingredient) {
            $required = $ingredient->pivot->quantity_required;
            if ($ingredient->current_stock < $required) {
                $unavailable[] = [
                    'ingredient' => $ingredient->name,
                    'required' => $required,
                    'available' => $ingredient->current_stock,
                    'unit' => $ingredient->unit,
                ];
            }
        }

        return $unavailable;
    }

    public function scopeActive($query)
    {
        return $query->where('is_active', true);
    }

    public function scopeAvailable($query)
    {
        return $query->where('is_available', true);
    }

    public function scopeInStock($query)
    {
        return $query->where(function ($q) {
            $q->where('track_inventory', false)
              ->orWhere('stock_quantity', '>', 0);
        });
    }

    public function scopeLowStock($query)
    {
        return $query->where('track_inventory', true)
            ->whereNotNull('low_stock_alert')
            ->whereRaw('stock_quantity <= low_stock_alert');
    }

    public function scopeByCategory($query, int $categoryId)
    {
        return $query->where('category_id', $categoryId);
    }

    public function scopeByKitchenStation($query, string $station)
    {
        return $query->whereJsonContains('kitchen_stations', $station);
    }

    public function scopeOrderable($query)
    {
        return $query->active()->available()->inStock();
    }
}