# Apaleo Integration Plan (brafa-laravel-livewire)

## Goal
Implement Apaleo as a new booking source so Brafa can:
- Connect to Apaleo via OAuth 2.0 Authorization Code (Connect app).
- Receive reservation updates via webhooks.
- Sync reservations into `bookings`.
- Reuse existing `bookings -> booking_codes -> Sciener` pipeline.
- Write generated passcodes back to Apaleo after successful lock sync.
- Show lock/code status in Apaleo One tabs.

## Product Decisions
1. **App model**: Apaleo Connect app, OAuth Authorization Code flow.
2. **Native integration**: Brafa-hosted integration + Apaleo One tabs (not in-Apaleo business logic).
3. **Source of truth**: Brafa DB for passcodes and sync state.
4. **Write-back target**: Reservation-level write-back first (`PATCH /booking/v1/reservations/{id}`), fallback to booking comment only if needed.
5. **Local key**: Use Apaleo reservation ID as Brafa `bookingId`; store booking ID separately.
6. **Sync model**: webhook-first + reconciliation job.

## Architecture Fit
Use existing pattern:
`Apaleo -> normalize -> bookings table -> compareBookingsWithCodesTable() -> booking_codes -> Sciener`

Avoid a parallel Sciener flow unless an Apaleo edge case forces it.

## Phase 0: Preconditions
- Refactor booking persistence before Apaleo:
  - Replace insert-style flow with an idempotent upsert behavior.
  - Preserve passcodes across ordinary updates.
  - Fix any update path that can overwrite passcode from date fields.
- Extract a reusable provider sync pattern:
  - Fetch remote records.
  - Normalize.
  - Upsert.
  - Compare/sync.
  - Handle missing/cancelled.

## Phase 1: Database
### 1. `apaleo_details`
Columns:
- `id`, `property_id`, `account_code`, `apaleo_property_id`
- `client_id`, `client_secret_encrypted`
- `access_token_encrypted`, `refresh_token_encrypted`, `token_expires_at`
- `webhook_subscription_id`, `reservation_ui_integration_id`, `booking_ui_integration_id`
- timestamps

### 2. `apaleo_reservation_mappings`
Columns:
- `id`, `property_id`
- `apaleo_reservation_id`, `apaleo_booking_id`
- `apaleo_external_id`, `apaleo_unit_id`, `apaleo_unit_name`
- `brafa_booking_id`
- `last_remote_hash`, `last_synced_at`
- timestamps

### 3. `apaleo_writebacks`
Columns:
- `id`, `property_id`, `apaleo_reservation_id`, `booking_id`
- `last_written_passcode`, `last_written_at`
- `last_write_status`, `last_error`
- timestamps

### 4. Optional `apaleo_unit_mappings`
Only if direct unit matching is not reliable.

## Phase 2: Services
Create:
- `App\Services\ApaleoAuthService`
- `App\Services\ApaleoReservationService`
- `App\Services\ApaleoWebhookService`
- `App\Services\ApaleoSyncService`
- `App\Services\ApaleoWritebackService`
- `App\Services\ApaleoUiIntegrationService`

Responsibilities (high level):
- Auth/token lifecycle.
- Reservation fetch + pagination + expansions.
- Webhook parse/dispatch.
- Normalization + booking upsert + compare trigger.
- Write-back with dedupe and error tracking.
- Apaleo One tab registration and secure URL management.

## Phase 3: Routes/Controllers
Add:
- `GET /apaleo/connect`
- `GET /apaleo/oauth/callback`
- `POST /apaleo/webhooks`
- `GET /apaleo/ui/reservation/secure-url`
- `GET /apaleo/ui/booking/secure-url`
- `GET /apaleo/ui/reservation`
- `GET /apaleo/ui/booking`

Controllers:
- `ApaleoOAuthController`
- `ApaleoWebhookController`
- `ApaleoUiController`

## Phase 4: Onboarding (`SetApiKey`)
- Add `selected_api === 'apaleo'` branch.
- Add fields:
  - `apaleo_client_id`
  - `apaleo_client_secret`
  - `apaleo_account_code`
  - `apaleo_property_id`
  - `apaleo_connect_mode`
- Require OAuth connect as canonical setup.
- Save details/config, then complete OAuth callback tasks:
  - store tokens
  - create webhook subscription
  - create Apaleo One tabs
  - initial sync
  - run compare/sync

## Phase 5: Reservation Sync
- Subscribe to reservation lifecycle topics (or `reservation/*`).
- Initial sync: import active/upcoming reservations with pagination (`pageSize=200`).
- Normalize to Brafa booking shape:
  - `bookingId = apaleo_reservation_id`
  - robust guest fallback chain
  - mapped room/unit
  - stable passcode behavior
- Handle unit reassignment and cancellations/no-shows/check-out/deletion.

## Phase 6: Passcode Stability
- Brafa generates passcode.
- Generate only for new booking without passcode.
- Keep passcode stable on regular updates.
- Rotate only on explicit regeneration/recreation.
- Add collision check scoped to property and active booking windows.

## Phase 7: Reuse Existing Compare/Sync Pipeline
After Apaleo upsert, invoke existing compare/reconcile path to manage booking codes and Sciener sync.

## Phase 8: Write-back to Apaleo
- Trigger write-back only after successful local lock sync.
- Primary: reservation-level patch.
- Fallback: booking-level comment if reservation patch cannot hold staff-visible passcode context.
- Deduplicate writes based on `apaleo_writebacks` state.
- Fail write-back independently (no rollback of local provisioning).

## Phase 9: Apaleo One UI
- Implement at least `ReservationDetailsTab`.
- Display reservation mapping, passcode, sync status, last sync, write-back status.
- Provide actions for retry/rewrite/regenerate (role-gated).
- Secure URL endpoint returns iframe URL + expiry timestamp.

## Phase 10: Jobs/Queues
Add queued jobs:
- `SyncApaleoReservationJob`
- `InitialApaleoSyncJob`
- `WriteApaleoPasscodeJob`
- `CreateApaleoWebhookSubscriptionJob`
- `CreateApaleoUiIntegrationJob`

Use retries/backoff for webhooks and write-back; centralize token refresh.

## Phase 11: Scopes
Start minimal and trim with live schema verification:
- `reservations.read`
- `reservations.manage`
- `setup.read`
- only add user/setup/UI-management scopes if required

## Phase 12: Testing
Unit tests:
- normalization
- passcode stability
- write-back dedupe
- unit mapping
- booking upsert behavior

Integration tests:
- OAuth callback token exchange
- webhook event processing
- reservation state transitions
- write-back success/failure behavior

E2E:
- connect account
- initial sync
- webhook change
- booking update
- Sciener sync
- Apaleo write-back
- Apaleo One status rendering

## Suggested Delivery Order
1. Fix booking upsert/passcode behavior.
2. Add Apaleo DB schema + models.
3. OAuth connect flow.
4. Webhooks + subscription bootstrap.
5. Initial fetch + normalization.
6. Upsert to bookings + existing compare/sync.
7. Write-back service.
8. Apaleo One tab.
9. Retry, observability, test hardening.

## v1 Non-goals
- Mobile key support
- Guest messaging via Apaleo
- Fully automatic room remapping UX
- Advanced shared-code behavior for multi-reservation booking rollups
- Store certification polish beyond minimum technical completeness

## Implementation Note (critical)
Before coding write-back payloads, validate current live Apaleo schema for writable reservation comment fields on:
- `PATCH /booking/v1/reservations/{id}`

If unavailable for intended staff-visible value, fallback to booking-level write-back.
