<?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\Support\Facades\DB;
use App\Models\PurchaseItem;
use App\Models\Wine;

class Purchase extends Model
{
    /** @use HasFactory<\Database\Factories\PurchaseFactory> */
    use HasFactory;
    protected $fillable = [
        'user_id',
        'wine_id',
        'amount',
        'price',
        'status',
        'purchased_at',
        'note',
    ];

    /**
     * Casts for attributes
     *
     * @var array
     */
    protected $casts = [
        'amount' => 'integer',
        'price' => 'decimal:2',
        'purchased_at' => 'datetime',
        'status' => 'string',
        'note' => 'string',
    ];

    public function user()
    {
        return $this->belongsTo(User::class, 'user_id');
    }

    public function wine()
    {
        return $this->belongsTo(Wine::class, 'wine_id');
    }

    /**
     * Purchase has many items (weak entity)
     */
    public function items(): HasMany
    {
        return $this->hasMany(PurchaseItem::class, 'purchase_id');
    }

    /**
     * Create a purchase with items and decrement wine stock atomically.
     *
     * $items = [ ['wine_id'=>1,'quantity'=>2,'unit_price'=>12.5], ... ]
     */
    public static function createWithItems(array $data, array $items): self
    {
        return DB::transaction(function () use ($data, $items) {
            $purchase = self::create($data);

            foreach ($items as $it) {
                $wine = Wine::findOrFail($it['wine_id']);

                $qty = (int) ($it['quantity'] ?? 1);
                if ($wine->bottles_in_stock !== null && $wine->bottles_in_stock < $qty) {
                    throw new \Exception("Insufficient stock for wine id {$wine->id}");
                }

                $unit = $it['unit_price'] ?? $wine->price_per_bottle ?? 0;
                $lineTotal = round($qty * $unit, 2);

                $purchase->items()->create([
                    'wine_id' => $wine->getKey(),
                    'quantity' => $qty,
                    'unit_price' => $unit,
                    'line_total' => $lineTotal,
                ]);

                // decrement stock if tracked
                if ($wine->bottles_in_stock !== null) {
                    $wine->decrement('bottles_in_stock', $qty);
                }
            }

            return $purchase;
        });
    }

}
