# Milestone 1 Implementation Summary & Testing Guide

## 📋 Branch Overview
**Branch:** `feature/main-20260603`  
**Date:** 2026-06-05  
**Goal:** Mobile customer authentication + placeholder WebView portal  

---

## ✅ All Tasks Completed (1-9, 11)

### Task 1: Customer Data Models
- Added `app/Models/Customer.php` — manages customer identity tied to Firebase UID + store
- Added `app/Models/CustomerDevice.php` — tracks FCM tokens for push notifications
- Created migrations: `create_customers_table`, `create_customer_devices_table`
- Relationships: Customer hasMany CustomerDevices

### Task 2: Firebase Auth Validation
- Added `app/Services/FirebaseAuthService.php` — validates Firebase ID tokens via Google Identity Toolkit
- Created `config/firebase.php` — centralizes Firebase settings
- Graceful error handling (timeouts, network failures, invalid tokens)
- Tested with mocked HTTP responses

### Task 3: FCM Device Registration Endpoint
- Added `POST /mobile/api/save_fcm_token.php` — mobile app registers FCM push tokens
- Auto-upserts customer by (firebase_uid + store_app_id)
- Deactivates tokens on other customers to prevent duplicates
- Returns legacy-compatible JSON response

### Task 4: Mobile Login Bridge
- Added `GET /mobile/mobile-login.php?token=X&store_app_id=Y` — OAuth redirect handler
- Validates Firebase ID token
- Creates/retrieves customer
- Sets session keys: `customer_id`, `firebase_uid`, `store_app_id`, `customer_name`
- Redirects to `/portal` for WebView display

### Task 5: Customer Auth Middleware
- Added `app/Http/Middleware/CustomerAuth.php` — protects portal routes
- Validates customer session exists
- Binds customer model to request for easy access
- Registered as `customer.auth` middleware alias
- Clears stale sessions if customer was deleted

### Task 6: Portal Home Placeholder
- Added `app/Http/Controllers/Mobile/PortalHomeController.php` — renders mobile portal views
- Routes: `GET /portal` (home), `POST /portal/logout` (sign-out)
- Mobile-first layout: `resources/views/mobile/layouts/app.blade.php`
- Placeholder home: `resources/views/mobile/home.blade.php` (welcome, loyalty card, features coming soon)
- Sign-out page: `resources/views/mobile/signed-out.blade.php`

### Task 7: Debug Log Endpoint
- Added `POST /mobile/api/debug_log.php` — mobile app sends diagnostic logs
- Stores to `storage/logs/mobile-debug-{Y-m-d}.log` (daily files)
- Appends multiple calls to same file
- Returns stored entry count

### Task 8: Route Registration
- Mobile routes (no CSRF):
  - `POST /mobile/api/save_fcm_token.php` → registerDevice()
  - `POST /mobile/api/debug_log.php` → debugLog()
  - `GET /mobile/mobile-login.php` → loginBridge()
- Portal routes (customer.auth middleware):
  - `GET /portal` → PortalHomeController@index
  - `POST /portal/logout` → PortalHomeController@logout
- Notification routes (auth + verified middleware):
  - Full CRUD: `GET|POST|PUT|DELETE /notifications`
  - Send action: `POST /notifications/{id}/send`

### Task 9: Firebase Config
- `config/firebase.php` — reads env vars with sensible defaults
- `.env.example` — includes Firebase variables
- Identity Toolkit URL + HTTP timeout configurable
- Service account path for FCM V1 API
- iOS bundle ID for APNs topic header

### Task 11: Push Notification System (Admin → Customer Devices)
- Added `app/Services/FCMNotificationService.php` — sends push notifications via FCM V1 API
  - OAuth2 authentication using service account JSON (JWT assertion → access token)
  - Platform-specific payloads (Android high priority + channel_id, iOS APNs priority 10 + badge)
  - Auto-deactivates stale FCM tokens on 404 HTTP responses from Google
  - Methods: `sendToAllCustomers()`, `sendToStoreCustomers()`, `sendToDevices()`
- Added `app/Http/Controllers/NotificationController.php` — full CRUD + send
  - `index()` — list with status filter (draft/scheduled/sent/failed)
  - `create()` — auto-loads user’s store_app_ids from brands → customers (no manual entry)
  - `store()` — create draft or scheduled notification
  - `show()` — view with paginated recipient delivery status
  - `edit()/update()` — modify draft notifications
  - `send()` — trigger FCM delivery based on target_type
  - `destroy()` — delete draft notifications only
  - Owner authorization on all actions
- Added `app/Models/Notification.php` — notification records
- Added `app/Models/NotificationRecipient.php` — per-device delivery tracking
- Created 4 Blade views: `notifications/index`, `create`, `edit`, `show`
- Added sidebar navigation link (bell icon) in `layouts/navigation.blade.php`
- Added `Brand::customers()` HasMany relationship
- Created 14 feature tests (all passing)

---

## 🎯 What Was Built

### Mobile App Flow
```
Mobile App (Firebase Auth) 
  → GET /mobile/mobile-login.php?token=JWT&store_app_id=friezandburgz
  → Laravel validates token via Firebase
  → Creates/updates Customer record
  → Sets session
  → Redirects to /portal
  → WebView loads portal home (mobile-optimized Blade)
```

### Key Endpoints

| Endpoint | Method | Auth | Purpose |
|----------|--------|------|---------|
| `/mobile/api/save_fcm_token.php` | POST | None | Register FCM push token |
| `/mobile/api/debug_log.php` | POST | None | Store mobile debug logs |
| `/mobile/mobile-login.php` | GET | Firebase token | OAuth login bridge |
| `/portal` | GET | customer.auth | Placeholder home page |
| `/portal/logout` | POST | customer.auth | Sign out customer |

---

## 🌐 How to Access the Mobile Portal

### Option 1: Direct URL Testing (Postman / Browser)
1. Get a valid Firebase ID token from your mobile app (or Firebase Console)
2. Visit:
   ```
   http://localhost/mobile/mobile-login.php?token=YOUR_TOKEN&store_app_id=friezandburgz
   ```
3. If token is valid → redirects to `/portal` (session-protected page)
4. If token is invalid → returns 401

### Option 2: Via Mobile App WebView
1. Update `lib/config/app_config.dart` in mobile app:
   ```dart
   static const String backendUrl = 'https://icard.orderbuddy.tech/mobile';
   ```
2. App signs in with Firebase
3. App receives ID token and redirects to WebView at `/portal`
4. WebView displays the mobile portal

### Option 3: Direct Session Access (Testing)
1. Create a customer in database:
   ```sql
   INSERT INTO customers (firebase_uid, store_app_id, name) 
   VALUES ('test_uid_123', 'friezandburgz', 'Test User');
   ```
2. Set session manually in Laravel Tinker:
   ```bash
   php artisan tinker
   >>> Session::put('customer_id', 1);
   >>> Session::put('firebase_uid', 'test_uid_123');
   >>> Session::put('store_app_id', 'friezandburgz');
   >>> Session::put('customer_name', 'Test User');
   ```
3. Visit `http://localhost/portal` — sees home page

---

## 📊 Test Results (All Passing)

### Full Test Suite: 35+ tests passed
- Task 1 (Customer Model): 1 passed
- Task 2 (Firebase Service): 1 passed
- Task 3 (Device Registration): 4 passed
- Task 4 (Login Bridge): 3 passed
- Task 5 (Middleware): 3 passed
- Task 6 (Portal Home): 3 passed
- Task 7 (Debug Log): 6 passed
- Task 11 (Notifications): 14 passed
- Baseline Examples: 2 passed

**Total: 35+ passed, 0 failed, 0 warnings**

---

## 🚀 Deployment & Testing Steps

### Step 1: Set Environment Variables
Create/update `.env` file:
```env
# Firebase (from mobile app firebase_options.dart)
FIREBASE_PROJECT_ID=restaurant-loyalty-app-cdd0a
FIREBASE_WEB_API_KEY=AIzaSyBzQ7A-lyse6PQ4yFwFo7QWFeRrdzUgOSI
FIREBASE_IDENTITY_TOOLKIT_URL=https://identitytoolkit.googleapis.com/v1/accounts:lookup
FIREBASE_HTTP_TIMEOUT_SECONDS=10

# Mobile Portal
MOBILE_PORTAL_DEFAULT_STORE=friezandburgz
```

### Step 2: Run Migrations
```bash
php artisan migrate
# Creates: customers, customer_devices tables
```

### Step 3: Test Endpoints with Postman

**A. Register FCM Token**
```
POST http://localhost/mobile/api/save_fcm_token.php
Content-Type: application/json

{
  "firebase_uid": "AbCdEf123...",
  "email": "user@example.com",
  "display_name": "John Doe",
  "fcm_token": "dXXXX...long_token...",
  "device_type": "android",
  "store_app_id": "friezandburgz"
}
```
Expected response:
```json
{
  "success": true,
  "message": "User and token saved/updated",
  "token_received_prefix": "dXXXX...",
  "token_saved_prefix": "dXXXX...",
  "token_saved_updated_at": "2026-06-05 12:00:00"
}
```

**B. Send Debug Log**
```
POST http://localhost/mobile/api/debug_log.php
Content-Type: application/json

{
  "store_app_id": "friezandburgz",
  "logs": [
    "App started",
    "User logged in",
    {"event": "transaction", "amount": 50.00}
  ]
}
```
Expected response:
```json
{
  "success": true,
  "message": "Debug logs stored",
  "stored": 3
}
```

**C. Login (OAuth Bridge)**
```
GET http://localhost/mobile/mobile-login.php?token=FIREBASE_ID_TOKEN&store_app_id=friezandburgz
```
Expected: HTTP 302 redirect to `/portal` with session set

**D. View Portal (Authenticated)**
```
GET http://localhost/portal
[Session must contain: customer_id, firebase_uid, store_app_id, customer_name]
```
Expected: Returns Blade template with:
- Welcome greeting (customer name)
- Loyalty points card
- Feature placeholders (greyed out)
- Sign-out button

**E. Logout**
```
POST http://localhost/portal/logout
[Session required]
```
Expected: Clears session, returns "Signed out successfully" page

### Step 4: Test View Files Rendering
```bash
# Verify views exist and compile
php artisan view:cache

# Test view compile
php artisan tinker
>>> view('mobile.home', ['customerName' => 'Test', 'loyaltyPoints' => 100])->render();
```

### Step 5: Check Log Output
```bash
# View stored debug logs
cat storage/logs/mobile-debug-2026-06-05.log
```

---

## 📁 File Changes Summary

### New Files Added
- Database migrations (4 files: customers, customer_devices, notifications, notification_recipients)
- Models: Customer, CustomerDevice, Notification, NotificationRecipient
- Services: FirebaseAuthService, FCMNotificationService
- Controllers: MobileApiController, MobileAuthController, PortalHomeController, NotificationController
- Middleware: CustomerAuth
- Views: mobile/layouts/app, mobile/home, mobile/signed-out, notifications/index, notifications/create, notifications/edit, notifications/show
- Config: firebase.php
- Factories: NotificationFactory, CustomerFactory, CustomerDeviceFactory, BrandFactory
- Tests: 8 test files (7 mobile + 1 notification)

### Modified Files
- `routes/web.php` — added mobile + portal + notification routes
- `.env.example` — added Firebase + FCM variables
- `bootstrap/app.php` — registered middleware alias
- `app/Models/Brand.php` — added `customers()` relationship
- `resources/views/layouts/navigation.blade.php` — added Notifications sidebar link
- `config/firebase.php` — added service_account_path + ios_bundle_id

### Key Locations
```
app/
  Http/Controllers/
    Mobile/
      MobileApiController.php       (registerDevice, debugLog)
      MobileAuthController.php      (loginBridge)
      PortalHomeController.php      (index, logout)
    NotificationController.php      (index, create, store, show, edit, update, destroy, send)
  Http/Middleware/
    CustomerAuth.php
  Models/
    Customer.php
    CustomerDevice.php
    Notification.php
    NotificationRecipient.php
  Services/
    FirebaseAuthService.php
    FCMNotificationService.php
config/
  firebase.php
resources/views/
  mobile/
    layouts/app.blade.php
    home.blade.php
    signed-out.blade.php
  notifications/
    index.blade.php
    create.blade.php
    edit.blade.php
    show.blade.php
tests/Feature/
  Mobile*.php test files
  PortalHome*.php test files
  NotificationControllerTest.php
```

---

## ⚠️ Important Notes

### Push Notifications (Completed in This Milestone)
Push notifications were originally planned for a later milestone but were brought forward and implemented.
The admin can now create and send FCM push notifications to customer devices from `/notifications`.

### Dashboard vs. Portal
- **Admin Dashboard** (`/dashboard`) — for restaurant owners/managers, protected by `auth` + `verified` middleware
- **Mobile Portal** (`/portal`) — for customers, protected by `customer.auth` middleware
- **Notifications** (`/notifications`) — admin feature for sending push to customers, protected by `auth` + `verified`
- These are completely separate auth flows and user bases — no cross-interference

### WebView Access
The mobile portal is **not a separate web interface** like the admin dashboard.  
It's designed to be loaded in the mobile app's WebView after OAuth login.  
You can test it by:
1. Direct URL (Postman + manual session)
2. Mobile app integration (requires building mobile app with updated backend URL)

### Next Steps (Future Milestones)
- Task 10: Mobile app config change + device E2E testing
- Milestone 2: Customer features (menu browsing, cart, orders)
- Milestone 3: Loyalty points engine + rewards
- Milestone 4: Customer profile + delivery zone validation

---

## 🔍 Quick Reference

| What | Command |
|------|---------|
| Run all tests | `php artisan test` |
| Run notification tests | `php artisan test tests/Feature/NotificationControllerTest.php` |
| Run mobile tests | `php artisan test --filter=Mobile` |
| Clear cache | `php artisan cache:clear` |
| Clear views | `php artisan view:clear` |
| Tinker shell | `php artisan tinker` |
| Route list (mobile) | `php artisan route:list --path=mobile` |
| Route list (notifications) | `php artisan route:list --path=notifications` |
| View stored logs | `cat storage/logs/mobile-debug-*.log` |

---

Generated: 2026-06-05 (Updated: 2026-06-15)  
Branch: feature/main-20260603  
Status: ✅ All Tasks 1-9 + 11 Complete (Task 10 pending mobile app update)
