<?php

declare(strict_types=1);

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;

class Product extends Model
{
    protected $fillable = [
        'name',
        'price',
        'category',
        'description',
        'image_path',
        'is_active',
    ];

    protected $casts = [
        'price' => 'decimal:2',
        'is_active' => 'boolean',
    ];

    /**
     * Get the recipes / BOM for this product.
     */
    public function recipes(): HasMany
    {
        return $this->hasMany(Recipe::class);
    }

    /**
     * Get the transaction items for this product.
     */
    public function transactionItems(): HasMany
    {
        return $this->hasMany(TransactionItem::class);
    }

    /**
     * Get the outlet stock records for this product (for manual/retail stock).
     */
    public function outletProducts(): HasMany
    {
        return $this->hasMany(OutletProduct::class);
    }

    /**
     * Get the outlets tracking this product.
     */
    public function outlets(): BelongsToMany
    {
        return $this->belongsToMany(Outlet::class, 'outlet_products')
            ->withPivot('stock_qty', 'threshold_qty')
            ->withTimestamps();
    }

    /**
     * Check if product has a recipe.
     */
    public function hasRecipe(): bool
    {
        return $this->recipes()->exists();
    }

    /**
     * Check if product has sufficient stock at a given outlet.
     */
    public function checkStock(int $outletId, int $qty = 1, ?string $variant = null): bool
    {
        // 1. If product has a recipe (BOM), check ingredient stocks
        if ($this->hasRecipe()) {
            $recipeItems = $this->recipes()
                ->where(function ($query) use ($variant) {
                    $query->whereNull('variant')
                          ->orWhere('variant', $variant);
                })
                ->get();

            if ($recipeItems->isEmpty()) {
                return false;
            }

            foreach ($recipeItems as $item) {
                $outletIngredient = OutletIngredient::where('outlet_id', $outletId)
                    ->where('ingredient_id', $item->ingredient_id)
                    ->first();

                if (!$outletIngredient) {
                    return false;
                }

                $needed = $item->usage_qty * $qty;
                if ($outletIngredient->stock_qty < $needed) {
                    return false;
                }
            }

            return true;
        }

        // 2. If no recipe, check direct product stock (retail inventory)
        $outletProduct = OutletProduct::where('outlet_id', $outletId)
            ->where('product_id', $this->id)
            ->first();

        if (!$outletProduct) {
            return false;
        }

        return $outletProduct->stock_qty >= $qty;
    }

    /**
     * Get the modifiers associated with this product.
     */
    public function modifiers(): BelongsToMany
    {
        return $this->belongsToMany(Modifier::class, 'product_modifiers');
    }
}
