# Events / Webinars Core Module

## Goal
Convert a webinar or event into a monetization funnel:

`Visitor -> Event Registration -> Attendance -> Offer -> Paid Enrollment -> Attendance Confirmed`

## Database schema

### `events`
- Public event/webinar metadata
- Supports bilingual title/description/location
- Stores event timing, mode, meeting provider, and optional host

### `event_registrations`
- One row per visitor registration per event
- Unique by `(event_id, phone)` to prevent duplicate registrations
- Tracks attendance timestamp, UTM attribution, consents, and linked enrollment handoff

### `event_reminders`
- Queue-ready reminder plan per event registration
- Supports `confirm`, `24h`, `3h`, `1h`, `post_no_show`, and `offer_followup`

### `event_messages`
- Template storage for event reminder content per channel and locale

### `event_tracking`
- Server-side analytics events with sanitized payloads
- Stores event, registration, name, payload, IP, and user agent

### `event_offers`
- Offer unlocked after attendance
- Can point to a `course`, a `cohort`, or a fully custom CTA

## Web routes

### Public
- `/events/{event:slug}`: event landing page and public registration
- `/events/{event:slug}/join/{registration:public_id}`: signed secure join page
- `/events/{event:slug}/replay/{registration:public_id}`: signed replay/follow-up page
- `/events/{event:slug}/attendance/{registration:public_id}`: signed attendance confirmation page
- `/events/{event:slug}/offer/{registration:public_id}`: signed offer page

### Admin
- `/admin/events`: events index
- `/admin/events/create`: create event
- `/admin/events/{event}/edit`: edit event
- `/admin/events/{event}/registrations`: monitor registrations and funnel progress

## API routes

- `GET /api/v1/events`: published events only
- `GET /api/v1/events/{slug}`: published event detail
- `POST /api/v1/events/{slug}/register`: public event registration
- `POST /api/v1/events/{slug}/track`: analytics tracking endpoint

## Security

- Public registration is rate-limited to `10/minute/IP`
- Tracking endpoint is rate-limited separately
- Join and attendance/offer links use temporary signed URLs
- Join access also requires the registration access token and is rate-limited separately
- The public landing page never renders the raw Zoom/Meet join URL
- Join URLs are not written into analytics payloads or audit logs
- Event management is admin-only
- Teachers can view only their hosted events
- Event registration access is restricted to admins, hosted teachers, or the owning user
- Sensitive meeting data is never written into analytics payloads

## Integrations

- Reuses the existing registration flow via:
  - `StartOrResumeRegistration`
  - `ChooseCohort`
- Schedules event reminders through:
  - `EventReminderPlanner`
  - `EventReminderDispatcher`
- Dispatches due reminders through:
  - `php artisan events:dispatch-reminders`
- Syncs event funnel state from existing enrollment/payment events via:
  - `EnrollmentCreated`
  - `PaymentConfirmed`
- Writes audit entries through `AuditService`

## Demo seed

`EventDemoSeeder` creates:
- one published webinar
- one linked offer
- demo registered, attended, and paid registrations
- one linked payment and first-session attendance confirmation
- sample event message templates

## Tests

Focused coverage exists for:
- public funnel happy path
- duplicate registration protection
- rate limiting
- secure join access and public URL leak prevention
- admin/support/teacher access control

Run:

```powershell
php artisan test tests\Feature\Events\PublicEventFunnelTest.php tests\Feature\Admin\EventAdminAccessTest.php
```
