# WooNooW API Routes Standard

## Namespace
All routes use: `woonoow/v1`

## Route Naming Convention

### Pattern
```
/{resource}                    # List/Create
/{resource}/{id}               # Get/Update/Delete single item
/{resource}/{action}           # Special actions
/{resource}/{id}/{sub}         # Sub-resources
```

### Rules
1. ✅ Use **plural nouns** for resources (`/products`, `/orders`, `/customers`)
2. ✅ Use **kebab-case** for multi-word resources (`/pickup-locations`)
3. ✅ Use **specific action names** to avoid conflicts (`/products/search`, `/orders/preview`)
4. ❌ Never create generic routes that might conflict (`/products` vs `/products`)
5. ❌ Never use verbs as resource names (`/get-products` ❌, use `/products` ✅)

---

## Current Routes Registry

### Products Module (`ProductsController.php`)
```
GET    /products                    # List products (admin)
GET    /products/{id}               # Get single product
POST   /products                    # Create product
PUT    /products/{id}               # Update product
DELETE /products/{id}               # Delete product
GET    /products/categories         # List categories
POST   /products/categories         # Create category
GET    /products/tags               # List tags
POST   /products/tags               # Create tag
GET    /products/attributes         # List attributes
```

### Orders Module (`OrdersController.php`)
```
GET    /orders                      # List orders
GET    /orders/{id}                 # Get single order
POST   /orders                      # Create order
PUT    /orders/{id}                 # Update order
DELETE /orders/{id}                 # Delete order
POST   /orders/preview              # Preview order totals
GET    /products/search             # Search products for order form (⚠️ Special route)
GET    /customers/search            # Search customers for order form (⚠️ Special route)
```

**⚠️ Important:** 
- `/products/search` is owned by OrdersController (NOT ProductsController)
- This is for lightweight product search in order forms
- ProductsController owns `/products` for full product management

### Customers Module (`CustomersController.php` - Future)
```
GET    /customers                   # List customers
GET    /customers/{id}              # Get single customer
POST   /customers                   # Create customer
PUT    /customers/{id}              # Update customer
DELETE /customers/{id}              # Delete customer
```

**⚠️ Important:**
- `/customers/search` is already used by OrdersController
- CustomersController will own `/customers` for full customer management
- No conflict because routes are specific

### Coupons Module (`CouponsController.php`) ✅ IMPLEMENTED
```
GET    /coupons                     # List coupons (with pagination, search, filter)
GET    /coupons/{id}                # Get single coupon
POST   /coupons                     # Create coupon
PUT    /coupons/{id}                # Update coupon
DELETE /coupons/{id}                # Delete coupon
POST   /coupons/validate            # Validate coupon code (OrdersController)
```

**Implementation Details:**
- **List:** Supports pagination (`page`, `per_page`), search (`search`), filter by type (`discount_type`)
- **Create:** Validates code uniqueness, requires `code`, `amount`, `discount_type`
- **Update:** Full coupon data update, code cannot be changed after creation
- **Delete:** Supports force delete via query param
- **Validate:** Handled by OrdersController for order context

**Note:**
- `/coupons/validate` is in OrdersController (order-specific validation)
- CouponsController owns `/coupons` for coupon CRUD management
- No conflict because validate is a specific action route

### Settings Module (`SettingsController.php`)
```
GET    /settings                    # Get all settings
PUT    /settings                    # Update settings
GET    /settings/store              # Get store settings
GET    /settings/tax                # Get tax settings
GET    /settings/shipping           # Get shipping settings
GET    /settings/payments           # Get payment settings
```

### Analytics Module (`AnalyticsController.php`)
```
GET    /analytics/overview          # Dashboard overview
GET    /analytics/products          # Product analytics
GET    /analytics/orders            # Order analytics
GET    /analytics/customers         # Customer analytics
```

### Licensing Module (`LicensesController.php`)
```
# Admin Endpoints (admin auth required)
GET    /licenses                     # List licenses (with pagination, search)
GET    /licenses/{id}                # Get single license
POST   /licenses                     # Create license
PUT    /licenses/{id}                # Update license
DELETE /licenses/{id}                # Delete license

# Public Endpoints (for client software validation)
POST   /licenses/validate            # Validate license key
POST   /licenses/activate            # Activate license on domain
POST   /licenses/deactivate          # Deactivate license from domain

# OAuth Endpoints (user auth required)
GET    /licenses/oauth/validate      # Validate OAuth state and license ownership
POST   /licenses/oauth/confirm       # Confirm activation and generate token
```

**Implementation Details:**
- **List:** Supports pagination (`page`, `per_page`), search by key/email
- **activate:** Supports Simple API and OAuth modes
- **OAuth flow:** `oauth/validate` + `oauth/confirm` for secure user verification
- See `LICENSING_MODULE.md` for full OAuth flow documentation

---

## Conflict Prevention Rules

### 1. Resource Ownership
Each resource has ONE primary controller:
- `/products` → `ProductsController`
- `/orders` → `OrdersController`
- `/customers` → `CustomersController` (future)
- `/coupons` → `CouponsController` (future)

### 2. Cross-Resource Operations
When one module needs data from another resource, use **specific action routes**:

**✅ Good:**
```php
// OrdersController needs product search
register_rest_route('woonoow/v1', '/products/search', [...]);

// OrdersController needs customer search
register_rest_route('woonoow/v1', '/customers/search', [...]);

// OrdersController needs coupon validation
register_rest_route('woonoow/v1', '/orders/validate-coupon', [...]);
```

**❌ Bad:**
```php
// OrdersController trying to own /products
register_rest_route('woonoow/v1', '/products', [...]);  // CONFLICT!

// OrdersController trying to own /customers
register_rest_route('woonoow/v1', '/customers', [...]);  // CONFLICT!
```

### 3. Sub-Resource Pattern
Use sub-resources for related data:

**✅ Good:**
```php
// Order-specific coupons
GET /orders/{id}/coupons           # List coupons applied to order
POST /orders/{id}/coupons          # Apply coupon to order
DELETE /orders/{id}/coupons/{code} # Remove coupon from order

// Order-specific notes
GET /orders/{id}/notes             # List order notes
POST /orders/{id}/notes            # Add order note
```

### 4. Action Routes
Use descriptive action names to avoid conflicts:

**✅ Good:**
```php
POST /orders/preview               # Preview order totals
POST /orders/calculate-shipping    # Calculate shipping
GET /products/search               # Search products (lightweight)
GET /coupons/validate              # Validate coupon code
```

**❌ Bad:**
```php
POST /orders/calc                  # Too vague
GET /search                        # Too generic
GET /validate                      # Too generic
```

---

## Registration Order

WordPress REST API uses **first-registered-wins** for route conflicts.

### Controller Registration Order (in `Routes.php`):
```php
1. SettingsController
2. ProductsController      # Registers /products first
3. OrdersController        # Can use /products/search (no conflict)
4. CustomersController     # Will register /customers
5. CouponsController       # Will register /coupons
6. AnalyticsController
```

**⚠️ Critical:** 
- ProductsController MUST register before OrdersController
- This ensures `/products` is owned by ProductsController
- OrdersController can safely use `/products/search` (different path)

---

## Testing for Conflicts

### 1. Check Route Registration
```php
// Add to Routes.php temporarily
add_action('rest_api_init', function() {
    $routes = rest_get_server()->get_routes();
    error_log('WooNooW Routes: ' . print_r($routes['woonoow/v1'], true));
}, 999);
```

### 2. Test API Endpoints
```bash
# Test product list (should hit ProductsController)
curl -X GET "https://site.local/wp-json/woonoow/v1/products"

# Test product search (should hit OrdersController)
curl -X GET "https://site.local/wp-json/woonoow/v1/products/search?s=test"

# Test customer search (should hit OrdersController)
curl -X GET "https://site.local/wp-json/woonoow/v1/customers/search?s=john"
```

### 3. Frontend API Calls
```typescript
// ProductsApi - Full product management
ProductsApi.list()          → GET /products
ProductsApi.get(id)         → GET /products/{id}
ProductsApi.create(data)    → POST /products

// OrdersApi - Product search for orders
ProductsApi.search(query)   → GET /products/search

// CustomersApi - Customer search for orders
CustomersApi.search(query)  → GET /customers/search
```

---

## Future Considerations

### When Adding New Modules:

1. **Check existing routes** - Review this document
2. **Choose specific names** - Avoid generic routes
3. **Use sub-resources** - For related data
4. **Update this document** - Add new routes to registry
5. **Test for conflicts** - Use testing methods above

### Frontend Module (Customer-Facing) ✅ IMPLEMENTED

#### **ShopController.php**
```
GET    /shop/products              # List products (public)
GET    /shop/products/{id}         # Get single product (public)
GET    /shop/categories            # List categories (public)
GET    /shop/search                # Search products (public)
```

**Implementation Details:**
- **List:** Supports pagination, category filter, search, orderby
- **Single:** Returns detailed product info (variations, gallery, related products)
- **Categories:** Returns categories with images and product count
- **Search:** Lightweight product search (max 10 results)

#### **CartController.php**
```
GET    /cart                       # Get cart contents
POST   /cart/add                   # Add item to cart
POST   /cart/update                # Update cart item quantity
POST   /cart/remove                # Remove item from cart
POST   /cart/apply-coupon          # Apply coupon to cart
POST   /cart/remove-coupon         # Remove coupon from cart
```

**Implementation Details:**
- Uses WooCommerce cart session
- Returns full cart data (items, totals, coupons)
- Public endpoints (no auth required)
- Validates product existence before adding

#### **AccountController.php**
```
GET    /account/orders             # Get customer orders (auth required)
GET    /account/orders/{id}        # Get single order (auth required)
GET    /account/profile            # Get customer profile (auth required)
POST   /account/profile            # Update profile (auth required)
POST   /account/password           # Update password (auth required)
GET    /account/addresses          # Get addresses (auth required)
POST   /account/addresses          # Update addresses (auth required)
GET    /account/downloads          # Get digital downloads (auth required)
```

**Implementation Details:**
- All endpoints require `is_user_logged_in()`
- Order endpoints verify customer owns the order
- Profile/address updates use WC_Customer class
- Password update verifies current password

**Note:**
- Frontend routes are customer-facing (public or logged-in users)
- Admin routes (ProductsController, OrdersController) are admin-only
- No conflicts because frontend uses `/shop`, `/cart`, `/account` prefixes

### WooCommerce Hook Bridge

### Get Hooks for Context
- **GET** `/woonoow/v1/hooks/{context}`
- **Purpose:** Capture and return WooCommerce action hook output for compatibility with plugins
- **Parameters:**
  - `context` (required): 'product', 'shop', 'cart', or 'checkout'
  - `product_id` (optional): Product ID for product context
- **Response:** `{ success: true, context: string, hooks: { hook_name: html_output } }`
- **Example:** `/woonoow/v1/hooks/product?product_id=123`

---

## Customer-Facing Frontend Routes are customer-facing (public or logged-in users)
- Admin routes (ProductsController, OrdersController) are admin-only
- No conflicts because frontend uses `/shop`, `/cart`, `/account` prefixes

### Reserved Routes (Do Not Use):
```
/products          # ProductsController (admin)
/orders            # OrdersController (admin)
/customers         # CustomersController (admin)
/coupons           # CouponsController (admin)
/settings          # SettingsController (admin)
/analytics         # AnalyticsController (admin)
/shop              # ShopController (customer)
/cart              # CartController (customer)
/account           # AccountController (customer)
```

### Safe Action Routes:
```
/products/search   # OrdersController (lightweight search)
/customers/search  # OrdersController (lightweight search)
/orders/preview    # OrdersController (order preview)
/coupons/validate  # CouponsController (coupon validation)
```

---

## Summary

✅ **Do:**
- Use plural nouns for resources
- Use specific action names
- Use sub-resources for related data
- Register controllers in correct order
- Update this document when adding routes

❌ **Don't:**
- Create generic routes that might conflict
- Use verbs as resource names
- Register same route in multiple controllers
- Forget to test for conflicts

**Remember:** First-registered-wins! Always check existing routes before adding new ones.
