<?php

use Illuminate\Support\Facades\Route;
use Modules\Bms\Http\Controllers\Api\CatalogController;
use Modules\Bms\Http\Controllers\Api\ClientAuthController;
use Modules\Bms\Http\Controllers\Api\ClientController;
use Modules\Bms\Http\Controllers\Api\DocumentController;
use Modules\Bms\Http\Controllers\Api\EmployeeAuthController;
use Modules\Bms\Http\Controllers\Api\EmployeeController;
use Modules\Bms\Http\Controllers\Api\MatchController;
use Modules\Bms\Http\Controllers\Api\PushController;
use Modules\Bms\Http\Controllers\Api\VisitController;
use Modules\Bms\Http\Controllers\Api\WizardController;

/*
|--------------------------------------------------------------------------
| BMS REST API v1  (prefix: /api/v1/bms, name: bms.api.*, group: api)
|--------------------------------------------------------------------------
| Two custom bearer-token guards (bms.api:client / bms.api:employee).
| Public funnel endpoints are anonymous (the unguessable wizard token is the
| identity) and rate-limited; OTP is reserved for the commitment moment.
*/

Route::get('/ping', fn () => response()->json([
    'module' => 'bms', 'version' => 'v1', 'time' => now()->toIso8601String(),
]))->name('ping');

// Public VAPID key for PWA push subscription.
Route::get('push/key', [PushController::class, 'key'])->name('push.key');

$token = '[A-Za-z0-9]+';

/* ---- Public funnel (rate-limited) ---------------------------------------- */
Route::middleware('throttle:90,1')->group(function () use ($token) {
    // Reference + catalog
    Route::get('reference', [CatalogController::class, 'reference'])->name('reference');
    Route::get('halls', [CatalogController::class, 'halls'])->name('halls');
    Route::get('halls/{id}', [CatalogController::class, 'hall'])->whereNumber('id')->name('hall');
    Route::get('halls/{id}/availability', [CatalogController::class, 'hallAvailability'])->whereNumber('id')->name('hall.availability');

    // Ad-hoc matching (no session)
    Route::post('match', [MatchController::class, 'run'])->name('match');

    // Wizard (progressive capture)
    Route::get('wizard/{token}', [WizardController::class, 'show'])->where('token', $token)->name('wizard.show');
    Route::put('wizard/{token}/step', [WizardController::class, 'step'])->where('token', $token)->name('wizard.step');
    Route::post('wizard/{token}/match', [MatchController::class, 'run'])->where('token', $token)->name('wizard.match');
    Route::post('wizard/{token}/select', [WizardController::class, 'select'])->where('token', $token)->name('wizard.select');
    Route::post('wizard/{token}/complete', [WizardController::class, 'complete'])->where('token', $token)->name('wizard.complete');
    Route::get('wizard/{token}/visit-plan', [VisitController::class, 'plan'])->where('token', $token)->name('wizard.visit_plan');
    Route::post('wizard/{token}/visits', [VisitController::class, 'book'])->where('token', $token)->name('wizard.visits');

    // Client verification (OTP at the commitment moment)
    Route::post('client/otp/verify', [ClientAuthController::class, 'otpVerify'])->name('client.otp.verify');
    Route::post('client/password/login', [ClientAuthController::class, 'passwordLogin'])->name('client.password.login');
    Route::get('client/dev-credentials', [ClientAuthController::class, 'devCredentials'])->name('client.dev.credentials');
    Route::post('client/dev-login', [ClientAuthController::class, 'devLogin'])->name('client.dev.login');
    Route::post('employee/login', [EmployeeAuthController::class, 'login'])->name('employee.login');
    Route::get('employee/dev-staff', [EmployeeAuthController::class, 'devStaff'])->name('employee.dev.staff');
    Route::post('employee/dev-login', [EmployeeAuthController::class, 'devStaffLogin'])->name('employee.dev.login');
});

/* ---- Tighter limits on session-start + OTP send -------------------------- */
Route::middleware('throttle:15,1')->group(function () {
    Route::post('wizard/start', [WizardController::class, 'start'])->name('wizard.start');
    Route::post('client/otp/request', [ClientAuthController::class, 'otpRequest'])->name('client.otp.request');
});

/* ---- Client-authenticated (P3) ------------------------------------------- */
Route::middleware('bms.api:client')->group(function () {
    Route::get('client/me', [ClientController::class, 'me'])->name('client.me');
    Route::post('client/password/set', [ClientAuthController::class, 'passwordSet'])->name('client.password.set');

    // Documents the client may view + contract acceptance
    Route::get('client/documents/{doc}/download', [DocumentController::class, 'clientDownload'])->whereNumber('doc')->name('client.document.download');
    Route::post('client/documents/{doc}/accept', [DocumentController::class, 'accept'])->whereNumber('doc')->name('client.document.accept');

    // Web-push subscription
    Route::post('client/push/subscribe', [PushController::class, 'subscribe'])->name('client.push.subscribe');
    Route::post('client/push/unsubscribe', [PushController::class, 'unsubscribe'])->name('client.push.unsubscribe');

    // Change requests (post-contract edits need staff approval)
    Route::post('client/change-request', [ClientController::class, 'changeRequest'])->name('client.change_request');
});

/* ---- Employee-authenticated (P2) ----------------------------------------- */
Route::middleware('bms.api:employee')->group(function () {
    Route::post('employee/logout', [EmployeeAuthController::class, 'logout'])->name('employee.logout');
    Route::get('employee/dashboard', [EmployeeController::class, 'dashboard'])->name('employee.dashboard');
    Route::post('employee/push/subscribe', [PushController::class, 'subscribe'])->name('employee.push.subscribe');
    Route::post('employee/push/unsubscribe', [PushController::class, 'unsubscribe'])->name('employee.push.unsubscribe');
    Route::get('employee/leads', [EmployeeController::class, 'leads'])->name('employee.leads');
    Route::get('employee/leads/{id}', [EmployeeController::class, 'leadDetail'])->whereNumber('id')->name('employee.lead');
    Route::post('employee/match', [EmployeeController::class, 'match'])->name('employee.match');
    Route::post('employee/holds', [EmployeeController::class, 'placeHold'])->name('employee.holds.place');
    Route::delete('employee/holds', [EmployeeController::class, 'releaseHold'])->name('employee.holds.release');

    // Bookings & money path (M7 ERP integration)
    Route::post('employee/leads/{id}/book', [EmployeeController::class, 'book'])->whereNumber('id')->name('employee.lead.book');
    Route::get('employee/bookings/{id}', [EmployeeController::class, 'bookingStatus'])->whereNumber('id')->name('employee.booking');
    Route::post('employee/bookings/{id}/confirm', [EmployeeController::class, 'confirmBooking'])->whereNumber('id')->name('employee.booking.confirm');
    Route::post('employee/bookings/{id}/contract', [EmployeeController::class, 'contractBooking'])->whereNumber('id')->name('employee.booking.contract');
    Route::post('employee/bookings/{id}/complete', [EmployeeController::class, 'completeBooking'])->whereNumber('id')->name('employee.booking.complete');
    Route::post('employee/bookings/{id}/payments', [EmployeeController::class, 'recordPayment'])->whereNumber('id')->name('employee.booking.pay');
    Route::get('employee/bookings/{id}/tasks', [EmployeeController::class, 'bookingTasks'])->whereNumber('id')->name('employee.booking.tasks');
    Route::get('employee/bookings/{id}/events', [EmployeeController::class, 'bookingEvents'])->whereNumber('id')->name('employee.booking.events');

    // Documents (contract / BEO / proposal / run-sheet)
    Route::get('employee/bookings/{id}/documents', [DocumentController::class, 'listForBooking'])->whereNumber('id')->name('employee.booking.documents');
    Route::post('employee/bookings/{id}/documents/{type}', [DocumentController::class, 'generate'])->whereNumber('id')->name('employee.booking.document.generate');
    Route::post('employee/leads/{id}/proposal', [DocumentController::class, 'generateProposal'])->whereNumber('id')->name('employee.lead.proposal');
    Route::get('employee/documents/{doc}/download', [DocumentController::class, 'download'])->whereNumber('doc')->name('employee.document.download');

    // Cancellation & reschedule (policy engine + refunds)
    Route::get('employee/bookings/{id}/cancel-quote', [EmployeeController::class, 'cancelQuote'])->whereNumber('id')->name('employee.booking.cancel_quote');
    Route::post('employee/bookings/{id}/cancel', [EmployeeController::class, 'cancelBooking'])->whereNumber('id')->name('employee.booking.cancel');
    Route::get('employee/bookings/{id}/reschedule-quote', [EmployeeController::class, 'rescheduleQuote'])->whereNumber('id')->name('employee.booking.reschedule_quote');
    Route::post('employee/bookings/{id}/reschedule', [EmployeeController::class, 'rescheduleBooking'])->whereNumber('id')->name('employee.booking.reschedule');
    Route::get('employee/tasks', [EmployeeController::class, 'tasks'])->name('employee.tasks');
    Route::get('employee/tasks/{id}', [EmployeeController::class, 'taskDetail'])->whereNumber('id')->name('employee.task.detail');
    Route::post('employee/tasks/{id}/accept', [EmployeeController::class, 'acceptTask'])->whereNumber('id')->name('employee.task.accept');
    Route::post('employee/tasks/{id}/complete', [EmployeeController::class, 'completeTask'])->whereNumber('id')->name('employee.task.complete');

    // Asset register (Release 2) — picker for the transfer form + browse/relocate
    Route::get('employee/assets', [EmployeeController::class, 'assets'])->name('employee.assets');
    Route::post('employee/assets/{id}/relocate', [EmployeeController::class, 'relocateAsset'])->whereNumber('id')->name('employee.assets.relocate');
    Route::get('employee/assets/{id}/history', [EmployeeController::class, 'assetHistory'])->whereNumber('id')->name('employee.assets.history');

    // Office visits
    Route::get('employee/visits', [EmployeeController::class, 'visits'])->name('employee.visits');

    // Maintenance queue (raise + work the workflow)
    Route::get('employee/maintenance', [EmployeeController::class, 'maintenance'])->name('employee.maintenance');
    Route::post('employee/maintenance', [EmployeeController::class, 'createMaintenance'])->name('employee.maintenance.create');
    Route::get('employee/maintenance/{id}', [EmployeeController::class, 'maintenanceDetail'])->whereNumber('id')->name('employee.maintenance.detail');
    Route::post('employee/maintenance/{id}/transition', [EmployeeController::class, 'transitionMaintenance'])->whereNumber('id')->name('employee.maintenance.transition');

    // Quality control (per-booking inspections)
    Route::get('employee/bookings/{id}/qc', [EmployeeController::class, 'qcInspection'])->whereNumber('id')->name('employee.booking.qc');
    Route::post('employee/qc/{id}/submit', [EmployeeController::class, 'qcSubmit'])->whereNumber('id')->name('employee.qc.submit');
    Route::post('employee/qc/{id}/voice', [EmployeeController::class, 'qcVoice'])->whereNumber('id')->name('employee.qc.voice');

    // AI assistant
    Route::post('employee/ai/chat', [EmployeeController::class, 'aiChat'])->name('employee.ai.chat');

    // Client change requests (approve / reject)
    Route::get('employee/change-requests', [EmployeeController::class, 'changeRequests'])->name('employee.change_requests');
    Route::post('employee/change-requests/{id}/decide', [EmployeeController::class, 'decideChangeRequest'])->whereNumber('id')->name('employee.change_request.decide');

    // Transfers + acceptance audit
    Route::get('employee/transfers', [EmployeeController::class, 'transfers'])->name('employee.transfers');
    Route::post('employee/transfers', [EmployeeController::class, 'createTransfer'])->name('employee.transfers.create');
    Route::get('employee/transfers/{id}', [EmployeeController::class, 'transferDetail'])->whereNumber('id')->name('employee.transfer');
    Route::post('employee/transfers/{id}/accept', [EmployeeController::class, 'acceptTransfer'])->whereNumber('id')->name('employee.transfers.accept');
});
