# Cart API Documentation

Base URL: `{APP_URL}/api/v1`

All authenticated endpoints require:

```
Authorization: Bearer {token}
Accept: application/json
Content-Type: application/json
```

---

## Authentication

| Flow              | How to identify cart owner                                |
| ----------------- | --------------------------------------------------------- |
| Logged-in user    | Bearer token (Sanctum) — `user_id` resolved from auth     |
| Guest / anonymous | Pass `guest_token` (UUID) in request body or query string |

---

## Endpoints

### 1. Get Cart

Resolves or creates the active cart for the current user/guest.

**Authenticated (user)**

```
GET /v1/cart
Authorization: Bearer {token}
```

**Guest**

```
GET /v1/cart/guest?guest_token={uuid}
```

**Response `200`**

```json
{
    "status": "success",
    "data": {
        "id": 1,
        "uid": "CART123ABC",
        "user_id": 5,
        "guest_token": null,
        "channel": "online",
        "status": "active",
        "coupon_code": null,
        "notes": null,
        "expires_at": null,
        "item_count": 2,
        "total_quantity": 3,
        "items": [
            {
                "id": 10,
                "product_id": 3,
                "product_variant_id": null,
                "quantity": 2,
                "notes": null,
                "product": { "id": 3, "name": "Plain T-Shirt", "sku": "TSH-001", "slug": "plain-t-shirt" },
                "variant": null,
                "created_at": "2026-03-11 10:00:00"
            },
            {
                "id": 11,
                "product_id": 7,
                "product_variant_id": 22,
                "quantity": 1,
                "notes": "Gift wrap please",
                "product": { "id": 7, "name": "Running Shoes", "sku": "SHO-007", "slug": "running-shoes" },
                "variant": { "id": 22, "title": "Size 42 / Black", "sku": "SHO-007-42-BLK" },
                "created_at": "2026-03-11 10:01:00"
            }
        ],
        "created_at": "2026-03-11 10:00:00",
        "updated_at": "2026-03-11 10:01:00"
    }
}
```

---

### 2. Add Item to Cart

If the same `product_id` + `product_variant_id` already exists in the cart, quantity is incremented automatically.

**Simple product (no variants)**

```
POST /v1/cart/items
Authorization: Bearer {token}
```

```json
{
    "product_id": 3,
    "quantity": 2
}
```

**Variant product (with attributes)**

```json
{
    "product_id": 7,
    "product_variant_id": 22,
    "quantity": 1,
    "notes": "Gift wrap please"
}
```

**Guest**

```
POST /v1/cart/guest/items
```

```json
{
    "guest_token": "550e8400-e29b-41d4-a716-446655440000",
    "product_id": 3,
    "quantity": 1
}
```

**Response `201`**

```json
{
  "status": "success",
  "message": "Item added to cart.",
  "data": { ...cart with items... }
}
```

**Validation errors `422`**

```json
{
    "message": "The product_id field is required.",
    "errors": {
        "product_id": ["The product_id field is required."]
    }
}
```

---

### 3. Update Cart Item Quantity

```
PATCH /v1/cart/items/{itemId}
Authorization: Bearer {token}
```

```json
{
    "quantity": 5
}
```

**Guest**

```
PATCH /v1/cart/guest/items/{itemId}
```

```json
{
    "guest_token": "550e8400-e29b-41d4-a716-446655440000",
    "quantity": 5
}
```

**Response `200`**

```json
{
  "status": "success",
  "message": "Cart item updated.",
  "data": { ...cart with updated items... }
}
```

**Not found `404`**

```json
{
    "status": "error",
    "message": "Cart item not found."
}
```

---

### 4. Remove Cart Item

```
DELETE /v1/cart/items/{itemId}
Authorization: Bearer {token}
```

**Guest**

```
DELETE /v1/cart/guest/items/{itemId}?guest_token={uuid}
```

**Response `200`**

```json
{
  "status": "success",
  "message": "Item removed from cart.",
  "data": { ...cart with remaining items... }
}
```

---

### 5. Clear Cart

Remove all items from the cart.

```
DELETE /v1/cart
Authorization: Bearer {token}
```

**Guest**

```
DELETE /v1/cart/guest?guest_token={uuid}
```

**Response `200`**

```json
{
  "status": "success",
  "message": "Cart cleared.",
  "data": { ...empty cart... }
}
```

---

### 6. Merge Guest Cart (on Login)

Call this immediately after a guest logs in to merge their guest cart items into their user cart.

```
POST /v1/cart/merge
Authorization: Bearer {token}
```

```json
{
    "guest_token": "550e8400-e29b-41d4-a716-446655440000",
    "channel": "online"
}
```

**Response `200`**

```json
{
  "status": "success",
  "message": "Guest cart merged.",
  "data": { ...merged cart with all items... }
}
```

---

## Status Codes

| Code  | Meaning              |
| ----- | -------------------- |
| `200` | Success              |
| `201` | Created (item added) |
| `404` | Cart item not found  |
| `422` | Validation error     |
| `500` | Server error         |

---

## Workflow Examples

### Online store — guest checkout flow

```
1. Guest opens product page
   → Generate UUID guest_token client-side, store in localStorage

2. Guest adds item
   POST /v1/cart/guest/items
   { "guest_token": "...", "product_id": 3, "quantity": 1 }

3. Guest adds variant product
   POST /v1/cart/guest/items
   { "guest_token": "...", "product_id": 7, "product_variant_id": 22, "quantity": 1 }

4. Guest logs in / registers
   → Receive Bearer token from auth endpoint

5. Merge guest cart
   POST /v1/cart/merge
   Authorization: Bearer {token}
   { "guest_token": "..." }

6. Proceed to checkout (use OrderProduct module)
```

### POS — direct add (no variants)

```
POST /v1/cart/items
Authorization: Bearer {staff_token}
{ "product_id": 5, "quantity": 3, "channel": "pos" }
```

### Buy Now (skip cart)

```
Place order directly via OrderProduct module with:
{ "cart_id": null, "product_id": ..., "product_variant_id": ... }
```

---

## Database Tables

| Table        | Description                                                   |
| ------------ | ------------------------------------------------------------- |
| `carts`      | Cart header — owner, channel, status                          |
| `cart_items` | Line items — `product_variant_id = NULL` means simple product |

## Key Design Note

`product_variant_id` on `cart_items` is **nullable**:

- `NULL` → simple product (no attributes selected)
- value → specific variant row (e.g. Size=M + Color=Blue resolved to `product_variants.id = 22`)
