# Document Upload & Verification Workflow

This document outlines the standardized workflow for handling file uploads, verification, and persistence within the Krow mobile application. This pattern is based on the `attire` module and is used as the reference for the `documents` and `certificates` modules.

## 1. Overview

The workflow follows a 4-step lifecycle:

1. **Selection**: Picking a PDF file locally via `FilePickerService`.
2. **Attestation**: Requiring the user to confirm the document is genuine before submission.
3. **Upload & Verification**: Pushing the file to storage and initiating a background verification job.
4. **Persistence**: Saving the record with its verification status to the database via Data Connect.

---

## 2. Technical Stack

| Service | Responsibility |
|---------|----------------|
| `FilePickerService` | PDF/file selection from device |
| `FileUploadService` | Uploads raw files to secure cloud storage |
| `SignedUrlService` | Generates secure internal/public links for viewing |
| `VerificationService` | Orchestrates AI or manual verification |
| `DataConnect` (Firebase) | Persists structured data and verification metadata |

---

## 3. Implementation Status

### ✅ Completed — Presentation Layer

#### Routing
- `StaffPaths.documentUpload` constant added to `core/lib/src/routing/staff/route_paths.dart`
- `StaffNavigator.toDocumentUpload({required StaffDocument document})` type-safe navigation helper added to `core/lib/src/routing/staff/navigator.dart`

#### Domain Layer
- `DocumentsRepository.uploadDocument(String documentId, String filePath)` method added to the repository interface.
- `UploadDocumentUseCase` created at `domain/usecases/upload_document_usecase.dart`, wrapping the repository call.
- `UploadDocumentArguments` value object holds `documentId` and `filePath`.

#### State Management
- `DocumentUploadStatus` enum: `initial | uploading | success | failure`
- `DocumentUploadState` (Equatable): tracks `status`, `isAttested`, `updatedDocument`, `errorMessage`
- `DocumentUploadCubit`: guards upload behind attestation check; emits success/failure; typed result as `StaffDocument`

#### UI — `DocumentUploadPage`
- Accepts `StaffDocument document` and optional `String? initialUrl` as route arguments
- Refactored into specialized widgets for maintainability:
  - `DocumentFileSelector`: Handles the file picking logic and "empty state" UI.
  - `DocumentSelectedCard`: Displays the selected file with "Replace" action.
  - `DocumentAttestationCheckbox`: Isolated checkbox logic for legal confirmation.
  - `DocumentUploadFooter`: Sticky bottom bar containing the checkbox and submission button.
- PDF file picker via `FilePickerService.pickFile(allowedExtensions: ['pdf'])`
- Attestation checkbox must be checked before the submit button is enabled
- Loading state: shows `CircularProgressIndicator` while uploading (replaces button — mirrors attire pattern)
- On success: shows `UiSnackbar` and calls `Modular.to.toDocuments()` to return to the list
- On failure: shows `UiSnackbar` with error message; stays on page for retry

#### UI Guidelines (For Documents & Certificates)
To ensure a consistent experience across all compliance uploads (documents, certificates), adhere to the following UI patterns:
1. **Header & Instructions:** Use `UiAppBar` with the item name as the title and description as the subtitle. Provide clear instructions at the top of the body (`UiTypography.body1m.textPrimary`).
2. **File Selection Card:** 
   - When empty: Show a neutral/primary bordered card inviting the user to pick a file.
   - When selected: Show an elegant card with `UiColors.bgPopup`, rounded corners (`UiConstants.radiusLg`), bordered by `UiColors.primary`.
   - The selected card must contain an identifying icon, the truncated file name, and an explicit inline action (e.g., "Replace" or "Upload") using `UiTypography.body3m.textSecondary`.
   - **Do not** embed native PDF viewers or link out to external readers.
3. **Bottom Footer / Attestation:**
   - Fix the attestation checkbox and the submit button to the bottom using `bottomNavigationBar` wrapped in a `SafeArea` and `Padding`.
   - The submit button state must be tightly coupled to both the file presence and the attestation state.

#### Module Wiring — `StaffDocumentsModule`
- `UploadDocumentUseCase` bound as lazy singleton
- `DocumentUploadCubit` bound (non-singleton, per-use)
- Upload route registered: `StaffPaths.documentUpload` → `DocumentUploadPage`
- Route arguments extracted: `data['document']` as `StaffDocument`, `data['initialUrl']` as `String?`

#### `DocumentsPage` Integration
- `DocumentCard.onTap` now calls `Modular.to.toDocumentUpload(document: doc)` instead of the old placeholder `pushNamed('./details')`

#### Localization
- Added `staff_documents.upload.*` keys to `en.i18n.json` and `es.i18n.json`
- Strings: `instructions`, `submit`, `select_pdf`, `attestation`, `success`, `error`
- Codegen (`dart run slang`) produces `TranslationsStaffDocumentsUploadEn` and its Spanish counterpart

#### DocumentStatus Mapping
- `DocumentStatus` mapping is centralized in `StaffConnectorRepositoryImpl`, collapsing complex backend states into domain levels:
  - `VERIFIED`, `AUTO_PASS`, `APPROVED` → `verified`
  - `UPLOADED`, `PENDING`, `PROCESSING`, `NEEDS_REVIEW`, `EXPIRING` → `pending`
  - `AUTO_FAIL`, `REJECTED`, `ERROR` → `rejected`
  - `MISSING` → `missing`
- A new `DocumentVerificationStatus` enum captures the full granularity of the backend state for detailed UI feedback (e.g., showing "Auto Fail" vs "Rejected").

---

### ✅ Completed — Data Layer
 
 #### Data Connect Integration
 - `StaffConnectorRepository` interface updated with `getStaffDocuments()` and `upsertStaffDocument()`.
 - `upsertStaffDocument` mutation in `legacy/dataconnect-v1/connector/staffDocument/mutations.gql` updated to accept `verificationId`.
 - `getStaffDocumentByKey` and `listStaffDocumentsByStaffId` queries updated to include `verificationId`.
 - SDK regenerated: `make dataconnect-generate-sdk ENV=dev`.
 
 #### Repository Implementation — `StaffConnectorRepositoryImpl`
 - **`getStaffDocuments()`**: 
   - Uses `Future.wait` to simultaneously fetch the full list of available `Document` types and the current staff's `StaffDocument` records.
   - Maps the master list of `Document` entities, joining them with any existing `StaffDocument` entry.
   - This ensures the UI always shows all required documents, even if they haven't been uploaded yet (status: `missing`).
   - Populates `verificationId` and `verificationStatus` for presentation layer mapping.
 - **`upsertStaffDocument()`**: 
   - Handles the upsert (create or update) of a staff document record.
   - Explicitly passes `documentUrl` and `verificationId`, ensuring metadata is persisted alongside the file reference.
 - **Status Mapping**:
   - `_mapDocumentStatus`: Collapses backend statuses into domain `verified | pending | rejected | missing`.
   - `_mapFromDCDocumentVerificationStatus`: Preserves the full granularity of the backend status for the UI/presentation layer.
 
 #### Feature Repository — `DocumentsRepositoryImpl`
 - Fixed to ensure all cross-cutting services (`FileUploadService`, `VerificationService`) are properly orchestrated.
 - **Verification Integration**: When a document is uploaded, a verification job is triggered, and its `verificationId` is saved to Data Connect immediately. This allows the UI to show a "Processing" state while the background job runs.

---

## 5. DocumentStatus Mapping Reference

The backend uses a richer enum than the domain layer. The mapping is standardized as follows:

| Backend `DocumentStatus` | Domain `DocumentStatus` | Notes |
|--------------------------|-------------------------|-------|
| `VERIFIED` | `verified` | Fully approved |
| `AUTO_PASS` | `verified` | AI approved |
| `APPROVED` | `verified` | Manually approved |
| `UPLOADED` | `pending` | File received, not yet processed |
| `PENDING` | `pending` | Queued for verification |
| `PROCESSING` | `pending` | AI analysis in progress |
| `NEEDS_REVIEW` | `pending` | AI unsure, human review needed |
| `EXPIRING` | `pending` | Approaching expiry (treated as pending for renewal) |
| `MISSING` | `missing` | Document not yet uploaded |
| `AUTO_FAIL` | `rejected` | AI rejected |
| `REJECTED` | `rejected` | Manually rejected |
| `ERROR` | `rejected` | System error during verification |

---

## 6. State Management Reference

```
DocumentUploadStatus
  ├── initial    — page just opened
  ├── uploading  — upload + verification in progress
  ├── success    — document saved; navigate back with result
  └── failure    — error; stay on page; show snackbar
```

**Cubit guards:**
- Upload is blocked unless `state.isAttested == true`
- Button is only enabled when both a file is selected AND attestation is checked

---

## 7. Future Considerations: Certificates

The implementation of the **Certificates** module should follow this exact pattern with a few key differences:
1. **Repository**: Use `StaffConnectorRepository.getStaffCertificates()` and `upsertStaffCertificate()`.
2. **Metadata**: Certificates often require an `expiryDate` and `issueingBody` which should be captured during the upload step if not already present in the schema.
3. **Verification**: If using the same `VerificationService`, ensure the `category` is set to `CERTIFICATE` instead of `DOCUMENT` to trigger appropriate verification logic.
4. **UI**: Mirror the `DocumentUploadPage` design but update the instructions and translation keys to reference certificates.
