import type { PageParams, Paginated } from '@/lib/api/types';

/**
 * Patient care-records domain — the **continuity-of-care** surface (b14). Two very different things share
 * one screen (the E2 record viewer):
 *
 *  1. **The nurse-authored, patient-scoped visit-note history** (سوابق) — **REAL** (b14 `care_records`
 *     GET/POST). Encrypted at rest, returned decrypted only after the clinical-access check passes; it is
 *     **patient-scoped, not booking-scoped**, so a new nurse taking over reads the whole history. A nurse
 *     with a qualifying booking may **append** a note; nobody edits it.
 *  2. **The family-owned editable record** (داروها/روتین/وظایف — medications/routine/tasks) — **NO backend
 *     exists** (neither the b14 contract nor the data model has it; **REQ-027**). The customer maintains it;
 *     it is mocked behind this seam. The domain is therefore **mock-primary** (see `constants.ts`).
 *
 * Load-bearing rules (contract + phase §5):
 *  - **Family-owned & patient-scoped.** The customer owns/edits medications/routine/tasks; the record
 *    persists across nurse changes (keyed to the patient, not the booking).
 *  - **Nurse is append-only.** The nurse view exposes the task checklist + a note composer + the read-only
 *    history — it must **never** wire `updateFamilyRecord` or any medication/routine/task editing.
 *  - **Strict access.** Owning customer / nurse with a confirmed booking / admin only. A `403` on a read →
 *    render a clear, non-leaking access-denied card (never partial clinical data).
 *  - **Clinical fields are sensitive** — never logged, never in `localStorage`, never in a query string.
 *
 * Shapes are derived from the b14 contract (`dev/contracts/domains/reviews-records.md` + swagger); the
 * family-record shapes are the client's own (REQ-027).
 */

/** The four tabs of the E2 record viewer (client display model). */
export type CareRecordTab = 'medications' | 'routine' | 'history' | 'tasks';
export const CARE_RECORD_TABS: readonly CareRecordTab[] = ['medications', 'routine', 'history', 'tasks'] as const;

// ── Family-owned editable record (REQ-027 — customer-maintained, no backend) ──────────────────────────────

/** A medication the family tracks. `id` is a stable client id (the record has no server identity yet). */
export interface Medication {
  id: string;
  name: string;
  dosage: string | null;
  frequency: string;
  timingNote: string | null;
}

/** A daily-routine item the family tracks (e.g. "measure blood pressure — morning"). */
export interface RoutineItem {
  id: string;
  label: string;
  timeOfDay: string | null;
  note: string | null;
}

/** A care task (the checklist the nurse ticks during a visit; the family authors the list). */
export interface CareTask {
  id: string;
  label: string;
  done: boolean;
}

/** The family-owned, patient-scoped editable record (REQ-027). */
export interface FamilyCareRecord {
  patientId: number;
  medications: Medication[];
  routine: RoutineItem[];
  tasks: CareTask[];
}

// ── Nurse-authored visit-note history (REAL — b14 care_records) ───────────────────────────────────────────

/** A structured "task X done/not-done" line the nurse ticked — **client-only** (the wire body is free text). */
export interface TaskResult {
  label: string;
  done: boolean;
}

/**
 * One nurse-authored visit note = one `CareRecordDto` (patient-scoped, newest-first). Read-only/append-only
 * from the client. `taskResults` is a client-only structured summary of the checklist the nurse ticked — the
 * wire `body` carries only free text, so on the real path the checklist is folded into `body`.
 */
export interface VisitNote {
  id: number;
  bookingId: number | null;
  nurseProfileId: number;
  nurseDisplayName: string | null;
  body: string;
  taskResults: TaskResult[];
  /** UTC ISO-8601 — Shamsi display is the client's job. */
  recordedAt: string;
}

// ── Access (REQ-027 — no wire endpoint; derived from the 403 on a read / the caller role) ─────────────────

export type RecordAccessDeniedReason = 'no_access' | 'not_found';

/**
 * Who may do what with this patient's record. `canEdit` is the owning customer only; `canAppendNote` is a
 * nurse with a qualifying booking only. A denied read surfaces `canView: false` + a `deniedReason`.
 */
export interface RecordAccess {
  canView: boolean;
  canEdit: boolean;
  canAppendNote: boolean;
  deniedReason?: RecordAccessDeniedReason;
}

/** The customer edit body (REQ-027) — replaces the provided sections of the family record. */
export interface UpdateFamilyRecordRequest {
  medications?: Medication[];
  routine?: RoutineItem[];
  tasks?: CareTask[];
}

/**
 * The nurse append body. Maps to the wire `WriteCareRecordBody` (`{ bookingId?, body }`): on the real path
 * `taskResults` is composed into `body` (the wire has no structured task field); the mock keeps it structured.
 */
export interface CreateVisitNoteRequest {
  bookingId?: number | null;
  body: string;
  taskResults?: TaskResult[];
}

/** `WriteCareRecordResult` — the append result. */
export interface WriteVisitNoteResult {
  id: number;
  patientId: number;
  recordedAt: string;
}

/**
 * The patient-records API seam — the real HTTP client and the in-memory mock both implement this; selection
 * is by config (`USE_PATIENT_RECORDS_MOCK`), never scattered `if (mock)` checks. `getPatientHistory` +
 * `createVisitNote` map real b14 routes; the family-record + access methods are REQ-027 gaps (mocked).
 */
export interface PatientRecordsApi {
  /** REQ-027 — the family-owned medications/routine/tasks (customer-maintained). */
  getFamilyRecord(patientId: number): Promise<FamilyCareRecord>;
  /** REQ-027 — who may view/edit/append for this patient (derived from the 403 on a read + the caller role). */
  getRecordAccess(patientId: number): Promise<RecordAccess>;
  /** REAL — the patient-scoped longitudinal visit-note history, newest-first, paged. */
  getPatientHistory(patientId: number, params: PageParams): Promise<Paginated<VisitNote>>;
  /** REQ-027 — the customer replaces sections of the family record. */
  updateFamilyRecord(patientId: number, body: UpdateFamilyRecordRequest): Promise<FamilyCareRecord>;
  /** REAL — a nurse appends a visit note (append-only; never edits the record). */
  createVisitNote(patientId: number, body: CreateVisitNoteRequest): Promise<WriteVisitNoteResult>;
}
