# Baskets API

The Baskets API allows you to manage shopping baskets for your users. Create baskets, add/remove items, and convert baskets into orders.

## Import

```typescript
import { Baskets, BasketStatus } from 'lua-cli';
```

## Overview

The Baskets API enables:
- Create and manage user shopping baskets
- Add and remove items from baskets
- Update basket metadata
- Filter baskets by status
- Convert baskets to orders
- Track total amount and item count

## Methods

| Method | Description |
|--------|-------------|
| `Baskets.create(data)` | Create a new basket |
| `Baskets.get(status?)` | Get all user baskets, optionally filtered by status |
| `Baskets.getById(basketId)` | Get a specific basket by ID |

## Basket Status

```typescript
enum BasketStatus {
  ACTIVE = 'active',
  CHECKED_OUT = 'checked_out',
  ABANDONED = 'abandoned'
}
```

## BasketInstance Methods

Once you have a basket instance, you can call these methods:

### `basket.addItem(item)`

Adds an item to the basket.

**Parameters:**
- `item` (object) - Item to add
  - `productId` (string) - Product ID
  - `quantity` (number) - Quantity
  - `metadata` (object, optional) - Custom metadata

**Returns:** `Promise<Basket>` - Updated basket data

**Example:**
```typescript
await basket.addItem({
  productId: 'prod_123',
  quantity: 2,
  metadata: { color: 'blue' }
});
```

### `basket.removeItem(itemId)`

Removes an item from the basket.

**Parameters:**
- `itemId` (string) - Item ID to remove

**Returns:** `Promise<Basket>` - Updated basket data

**Example:**
```typescript
await basket.removeItem('item_456');
```

### `basket.clear()`

Removes all items from the basket.

**Returns:** `Promise<Basket>` - Empty basket data

**Example:**
```typescript
await basket.clear();
```

### `basket.updateMetadata(metadata)`

Updates the basket's metadata.

**Parameters:**
- `metadata` (object) - Metadata object to merge

**Returns:** `Promise<Basket>` - Updated basket data

**Example:**
```typescript
await basket.updateMetadata({
  couponCode: 'SAVE10',
  giftWrap: true
});
```

### `basket.updateStatus(status)`

Updates the basket's status.

**Parameters:**
- `status` (BasketStatus) - New status

**Returns:** `Promise<Basket>` - Updated basket data

**Example:**
```typescript
await basket.updateStatus(BasketStatus.ABANDONED);
```

### `basket.placeOrder(data)`

Converts the basket into an order.

**Parameters:**
- `data` (object) - Order data
  - `shippingAddress` (object) - Shipping address
  - `billingAddress` (object) - Billing address
  - `paymentMethod` (string) - Payment method
  - Any other order-related data

**Returns:** `Promise<OrderInstance>` - Created order instance

**Example:**
```typescript
const order = await basket.placeOrder({
  shippingAddress: {
    street: '123 Main St',
    city: 'New York',
    zip: '10001'
  },
  paymentMethod: 'credit_card'
});
```

## Complete Examples

### Shopping Cart Tool

```typescript
import { LuaTool, Baskets, Products, BasketStatus } from 'lua-cli';
import { z } from 'zod';

export default class AddToCartTool implements LuaTool {
  name = 'add_to_cart';
  description = 'Add a product to the shopping cart';

  inputSchema = z.object({
    productId: z.string().describe('Product ID'),
    quantity: z.number().min(1).default(1).describe('Quantity')
  });

  async execute(input: z.infer<typeof this.inputSchema>) {
    // Get or create active basket
    const baskets = await Baskets.get(BasketStatus.ACTIVE);
    let basket = baskets.length > 0 ? baskets[0] : await Baskets.create({
      userId: 'current', // Automatically uses current user
      metadata: {}
    });

    // Verify product exists
    const product = await Products.getById(input.productId);
    if (!product) {
      return {
        success: false,
        error: 'Product not found'
      };
    }

    // Add item to basket
    await basket.addItem({
      productId: input.productId,
      quantity: input.quantity,
      metadata: {
        name: product.name,
        price: product.price
      }
    });

    return {
      success: true,
      message: `Added ${input.quantity}x ${product.name} to cart`,
      basketId: basket.id,
      itemCount: basket.itemCount,
      totalAmount: basket.totalAmount
    };
  }
}
```

### View Cart Tool

```typescript
import { LuaTool, Baskets, BasketStatus } from 'lua-cli';
import { z } from 'zod';

export default class ViewCartTool implements LuaTool {
  name = 'view_cart';
  description = 'View current shopping cart';

  inputSchema = z.object({});

  async execute() {
    const baskets = await Baskets.get(BasketStatus.ACTIVE);

    if (baskets.length === 0) {
      return {
        success: true,
        message: 'Your cart is empty',
        items: [],
        total: 0
      };
    }

    const basket = baskets[0];

    return {
      success: true,
      basketId: basket.id,
      items: basket.items,
      itemCount: basket.itemCount,
      totalAmount: basket.totalAmount,
      metadata: basket.metadata
    };
  }
}
```

### Remove from Cart Tool

```typescript
import { LuaTool, Baskets, BasketStatus } from 'lua-cli';
import { z } from 'zod';

export default class RemoveFromCartTool implements LuaTool {
  name = 'remove_from_cart';
  description = 'Remove an item from the shopping cart';

  inputSchema = z.object({
    itemId: z.string().describe('Item ID to remove')
  });

  async execute(input: z.infer<typeof this.inputSchema>) {
    const baskets = await Baskets.get(BasketStatus.ACTIVE);

    if (baskets.length === 0) {
      return {
        success: false,
        error: 'No active basket found'
      };
    }

    const basket = baskets[0];

    try {
      await basket.removeItem(input.itemId);

      return {
        success: true,
        message: 'Item removed from cart',
        itemCount: basket.itemCount,
        totalAmount: basket.totalAmount
      };
    } catch (error) {
      return {
        success: false,
        error: 'Item not found in basket'
      };
    }
  }
}
```

### Checkout Tool

```typescript
import { LuaTool, Baskets, BasketStatus, User } from 'lua-cli';
import { z } from 'zod';

export default class CheckoutTool implements LuaTool {
  name = 'checkout';
  description = 'Complete checkout and create an order';

  inputSchema = z.object({
    shippingAddress: z.object({
      street: z.string(),
      city: z.string(),
      state: z.string(),
      zip: z.string(),
      country: z.string()
    }),
    paymentMethod: z.enum(['credit_card', 'paypal', 'cash_on_delivery'])
  });

  async execute(input: z.infer<typeof this.inputSchema>) {
    // Get active basket
    const baskets = await Baskets.get(BasketStatus.ACTIVE);

    if (baskets.length === 0) {
      return {
        success: false,
        error: 'No active basket found'
      };
    }

    const basket = baskets[0];

    if (basket.itemCount === 0) {
      return {
        success: false,
        error: 'Cannot checkout with empty basket'
      };
    }

    // Get user info
    const user = await User.get();

    // Place order
    try {
      const order = await basket.placeOrder({
        shippingAddress: input.shippingAddress,
        billingAddress: input.shippingAddress, // Use same as shipping
        paymentMethod: input.paymentMethod,
        customerEmail: user.email,
        customerName: user.name
      });

      return {
        success: true,
        message: 'Order placed successfully!',
        orderId: order.orderId,
        totalAmount: basket.totalAmount,
        items: basket.items,
        estimatedDelivery: '3-5 business days'
      };
    } catch (error) {
      return {
        success: false,
        error: error instanceof Error ? error.message : 'Checkout failed'
      };
    }
  }
}
```

### Clear Cart Tool

```typescript
import { LuaTool, Baskets, BasketStatus } from 'lua-cli';
import { z } from 'zod';

export default class ClearCartTool implements LuaTool {
  name = 'clear_cart';
  description = 'Empty the shopping cart';

  inputSchema = z.object({});

  async execute() {
    const baskets = await Baskets.get(BasketStatus.ACTIVE);

    if (baskets.length === 0) {
      return {
        success: true,
        message: 'Cart is already empty'
      };
    }

    const basket = baskets[0];
    await basket.clear();

    return {
      success: true,
      message: 'Cart cleared successfully'
    };
  }
}
```

## Basket Properties

Basket instances provide direct access to properties:

```typescript
const basket = await Baskets.getById('basket_123');

console.log(basket.id);           // Basket ID
console.log(basket.items);        // Array of basket items
console.log(basket.itemCount);    // Total number of items
console.log(basket.totalAmount);  // Total basket value
console.log(basket.status);       // Basket status
console.log(basket.metadata);     // Custom metadata
```

## Best Practices

### ✅ DO

- Create one basket per user at a time
- Check for existing active baskets before creating new ones
- Validate products exist before adding to basket
- Use metadata for custom data (gift wrap, notes, etc.)
- Handle checkout failures gracefully
- Update basket status appropriately (active → checked_out)

### ❌ DON'T

- Don't create multiple active baskets for the same user
- Don't forget to validate product availability
- Don't skip error handling on addItem/checkout
- Don't place orders from empty baskets
- Don't assume basket items are still available during checkout

## Error Handling

```typescript
try {
  const basket = await Baskets.getById('basket_123');
  await basket.addItem({
    productId: 'prod_456',
    quantity: 1
  });
} catch (error) {
  if (error.message.includes('not found')) {
    console.log('Basket or product not found');
  } else if (error.message.includes('stock')) {
    console.log('Product out of stock');
  } else {
    console.log('Failed to add item:', error.message);
  }
}
```

## Common Patterns

### Get or Create Basket

```typescript
async function getOrCreateBasket(): Promise<BasketInstance> {
  const baskets = await Baskets.get(BasketStatus.ACTIVE);

  if (baskets.length > 0) {
    return baskets[0];
  }

  return await Baskets.create({
    userId: 'current',
    metadata: { createdAt: new Date().toISOString() }
  });
}
```

### Update Item Quantity

```typescript
async function updateItemQuantity(
  basket: BasketInstance,
  itemId: string,
  newQuantity: number
): Promise<void> {
  // Remove old item
  await basket.removeItem(itemId);

  // Add with new quantity
  const item = basket.items.find(i => i.id === itemId);
  if (item) {
    await basket.addItem({
      productId: item.productId,
      quantity: newQuantity,
      metadata: item.metadata
    });
  }
}
```

### Apply Coupon Code

```typescript
async function applyCoupon(
  basket: BasketInstance,
  couponCode: string
): Promise<void> {
  // Validate coupon (your business logic)
  const discount = validateCoupon(couponCode);

  await basket.updateMetadata({
    couponCode,
    discount,
    discountedTotal: basket.totalAmount - discount
  });
}
```

## Related APIs

- [Products API](./Products.md) - Product catalog management
- [Orders API](./Orders.md) - Order management after checkout
- [User API](./User.md) - User data for checkout

## See Also

- [E-commerce Guide](../guides/Ecommerce.md)
- [Checkout Flow](../guides/CheckoutFlow.md)
