## CartService Usage Guide

The `CartService` provides a unified API for managing shopping carts in your Laravel application, supporting both authenticated users and guest sessions. It fully accommodates extended `cart_items` fields like `inventory_id`, `shop_id`, `variant`, `price`, `discount`, `coupon`, and `data`.

---

### 1. Binding the Service

By default, Laravel auto-resolves the service via constructor injection. To enforce a singleton instance, register it in `AppServiceProvider`:

```php
// app/Providers/AppServiceProvider.php

public function register()
{
    $this->app->singleton(\App\Services\Models\CartService::class, function($app) {
        return new \App\Services\Models\CartService();
    });
}
```

---

### 2. Injecting the Service

Type-hint `CartService` in your controller constructor:

```php
use App\Services\Models\CartService;

class CartController extends Controller
{
    protected CartService $cart;

    public function __construct(CartService $cart)
    {
        $this->cart = $cart;
    }
}
```

Laravel’s IoC container will provide the configured instance.

---

### 3. Methods Overview

| Method                                                  | Signature                                                                                                                                                                               | Description                                                                           |
| ------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- |
| `add(...)`                                              | `add(int $productId, int $inventoryId, int $shopId, int $quantity = 1, array $variant = [], ?string $price = null, ?string $discount = null, ?string $coupon = null, array $data = [])` | Add/increment an item with all metadata.                                              |
| `update(...)`                                           | `update(int $productId, int $inventoryId, int $shopId, int $quantity, array $variant = [], ?string $price = null, ?string $discount = null, ?string $coupon = null, array $data = [])`  | Set item quantity and update metadata; removes if quantity ≤ 0.                       |
| `remove(int $productId, int $inventoryId, int $shopId)` | Remove the specific item row.                                                                                                                                                           |                                                                                       |
| `clear()`                                               | `clear(): void`                                                                                                                                                                         | Remove all items from current cart.                                                   |
| `items()`                                               | `items(): \Illuminate\Support\Collection`                                                                                                                                               | Retrieve all cart items with eager-loaded relations (`product`, `inventory`, `shop`). |
| `count()`                                               | `count(): int`                                                                                                                                                                          | Sum of all item quantities.                                                           |
| `total()`                                               | `total(): float`                                                                                                                                                                        | Sum of `price * quantity`. Note: ensure `price` is set per item.                      |

---

### 4. Extended `CartItem` Fields

Your `cart_items` migration may include extra columns:

* **Foreign keys**: `inventory_id`, `shop_id`
* **JSON**: `variant`, `data`
* **Strings**: `price`, `discount`, `coupon`

In your `CartItem` model, mark them fillable and cast:

```php
protected $fillable = [
    'cart_id',
    'product_id',
    'inventory_id',
    'shop_id',
    'variant',
    'price',
    'discount',
    'coupon',
    'data',
    'quantity',
];

protected $casts = [
    'variant'  => 'array',
    'data'     => 'array',
];
```

---

### 5. Example Controller Usage

#### Add to Cart

```php
public function add(Request $request)
{
    $d = $request->validate([
        'product_id'   => 'required|exists:products,id',
        'inventory_id' => 'required|exists:product_inventories,id',
        'shop_id'      => 'required|exists:shops,id',
        'quantity'     => 'sometimes|integer|min:1',
        'variant'      => 'nullable|array',
        'price'        => 'nullable|string',
        'discount'     => 'nullable|string',
        'coupon'       => 'nullable|string',
        'data'         => 'nullable|array',
    ]);

    $this->cart->add(
        $d['product_id'],
        $d['inventory_id'],
        $d['shop_id'],
        $d['quantity'] ?? 1,
        $d['variant']   ?? [],
        $d['price']     ?? null,
        $d['discount']  ?? null,
        $d['coupon']    ?? null,
        $d['data']      ?? []
    );

    return back()->with('success', 'Item added to cart.');
}
```

#### Update Cart Item

```php
public function update(Request $request)
{
    $d = $request->validate([
        'product_id'   => 'required|exists:products,id',
        'inventory_id' => 'required|exists:product_inventories,id',
        'shop_id'      => 'required|exists:shops,id',
        'quantity'     => 'required|integer|min:0',
        'variant'      => 'nullable|array',
        'price'        => 'nullable|string',
        'discount'     => 'nullable|string',
        'coupon'       => 'nullable|string',
        'data'         => 'nullable|array',
    ]);

    $this->cart->update(
        $d['product_id'],
        $d['inventory_id'],
        $d['shop_id'],
        $d['quantity'],
        $d['variant']   ?? [],
        $d['price']     ?? null,
        $d['discount']  ?? null,
        $d['coupon']    ?? null,
        $d['data']      ?? []
    );

    return redirect()->route('cart.index')->with('success', 'Cart updated.');
}
```

---

### 6. Blade Example Snippet

```blade
@foreach($items as $item)
  <div class="cart-item">
    <h4>{{ $item->product->name }} (Inv: {{ $item->inventory->id }})</h4>
    <p>Shop: {{ $item->shop->name }}</p>
    <p>Qty: {{ $item->quantity }}</p>
    @if($item->price)    <p>Price: {{ $item->price }}</p>@endif
    @if($item->discount) <p>Discount: {{ $item->discount }}</p>@endif
    @if($item->coupon)   <p>Coupon: {{ $item->coupon }}</p>@endif

    @if(! empty($item->variant))
      <ul>
        @foreach($item->variant as $k => $v)
          <li>{{ ucfirst($k) }}: {{ $v }}</li>
        @endforeach
      </ul>
    @endif

    @if(! empty($item->data))
      <pre>{{ json_encode($item->data, JSON_PRETTY_PRINT) }}</pre>
    @endif
  </div>
@endforeach
```

---

### 7. Routes

```php
use App\Http\Controllers\CartController;

Route::prefix('cart')->name('cart.')->namespace(CartController::class)->group(function () {
    Route::get('/',         'index')->name('index');
    Route::post('/add',     'add')->name('add');
    Route::post('/update',  'update')->name('update');
    Route::post('/remove',  'remove')->name('remove');
    Route::post('/clear',   'clear')->name('clear');
});
```

---

### 8. Merging Guest Cart on Login

Hook into the `Authenticated` event to merge session carts into user carts if desired. See earlier examples.

---

With these updates, the documentation now reflects your extended `cart_items` schema and shows exactly how to wire each field through the stack.
