# Mzaar Public API (v1)

A read-only JSON API (plus public booking and slope-report endpoints) that powers
the Mzaar mobile app. All routes are prefixed with `/api/v1` and require **no
authentication**. Responses follow Laravel's API Resource convention: collections
are wrapped in `{ "data": [...] }` and single resources in `{ "data": {...} }`.

Base URL (local): `http://localhost:8000/api/v1`

## Conventions

- All money values are returned as floats (e.g. `65` or `65.5`).
- Image fields are returned as absolute URLs in `*_url` keys.
- Validation failures return HTTP `422` with `{ "message", "errors": { field: [...] } }`.
- Unknown resources return HTTP `404`.

## Endpoints

### Health
| Method | Path | Description |
| ------ | ---- | ----------- |
| GET | `/health` | Liveness check. |

### Home
| Method | Path | Description |
| ------ | ---- | ----------- |
| GET | `/home` | Aggregated home payload: `summer_activities`, `winter_activities`, `slope_domains` (with live status), `snow_condition`, `weather`. |

### Activities
| Method | Path | Description |
| ------ | ---- | ----------- |
| GET | `/categories` | Activity categories. Add `?with_activities=1` to embed activities. |
| GET | `/activities` | List activities. Filters: `?season=winter\|summer\|all`, `?category=<slug>`, `?booking_type=court\|session\|...`. |
| GET | `/activities/{slug}` | Single activity with `pricing`, `venues`, `photos`, `category`. |

### Bookings
| Method | Path | Description |
| ------ | ---- | ----------- |
| GET | `/activities/{slug}/slots?date=YYYY-MM-DD&duration=60` | Available time slots for a date. |
| POST | `/activities/{slug}/bookings` | Create a booking. |
| GET | `/bookings/{confirmation_code}` | Look up a booking by its confirmation code. |

**Create booking body**

```json
{
  "guest_name": "Jane Doe",
  "guest_email": "jane@example.com",
  "guest_phone": "+961 3 000 000",
  "booking_date": "2026-01-20",
  "start_time": "10:00",
  "duration_minutes": 60,
  "num_people": 2,
  "venue_id": 1
}
```

- `start_time`, `duration_minutes`, `venue_id` are optional (depend on booking type).
- Court activities reject overlapping bookings; session activities enforce concurrent
  capacity; group activities enforce `min_group_size`.
- External-booking activities (e.g. Padel) return `422` with a `redirect_url`.

### Slopes & Conditions
| Method | Path | Description |
| ------ | ---- | ----------- |
| GET | `/slopes` | Slopes board grouped by domain, with `snow_condition` and `last_update`. |
| GET | `/slopes/{slug}` | Single slope with `latest_status` and recent `status_history`. |
| POST | `/slopes/{slug}/report` | Submit a public (guest, unverified) condition report. |
| GET | `/conditions/snow` | Current snow conditions. |
| GET | `/conditions/weather` | 5-day weather forecast. |

**Slope report body**

```json
{
  "status": "open",
  "crowd_level": 2,
  "snow_quality": 1,
  "visibility": 0,
  "reporter_name": "Guest Skier",
  "notes": "Great morning runs"
}
```

`crowd_level` 0–4, `snow_quality` 0–5, `visibility` 0–3 are mapped to their labels.

### Resort meta
| Method | Path | Description |
| ------ | ---- | ----------- |
| GET | `/ski-passes` | Ski pass products & prices. |
| GET | `/places` | Village points of interest (with `lat`/`lon`). |
| GET | `/operating-schedule` | Current operating hours. |

## Tests

Feature tests live in `tests/Feature/Api/ApiTest.php`:

```bash
php artisan test --filter=ApiTest
```
