import type { PageParams, Paginated } from '@/lib/api/types';
import { CONDITION_CODES, RELATION_CODES } from './constants';

/**
 * Patients domain — the care-recipient (patient) sub-domain, customer-scoped and
 * tenancy-enforced server-side. Shapes mirror the b3 contract
 * (`dev/contracts/domains/identity-profiles.md` → `PatientDto`) exactly; enums cross the
 * wire as stable string codes (money-and-types.md) mirrored here as unions.
 *
 * `relation` and `conditions` are **client-augmented**: they are not on the wire
 * `PatientDto` yet (filed as REQ-005 in requests/for-backend.md). The mock persists them;
 * the real client carries them through create/update so the just-edited card reflects the
 * choice, but they are not round-tripped by the server until the backend adds the columns.
 */

export type Gender = 'male' | 'female';
export type Relation = (typeof RELATION_CODES)[number];
export type ConditionCode = (typeof CONDITION_CODES)[number];

/** The b3 wire shape returned by every `patients/*` endpoint. */
export interface PatientDto {
  id: number;
  displayName: string;
  firstName: string;
  lastName: string;
  /** ISO date `YYYY-MM-DD`. */
  birthDate: string;
  gender: Gender;
  bloodType: string | null;
  /** Decrypted, owner-only free-text notes (E2 record viewer, deferred). */
  initialMedicalNotes: string | null;
  isActive: boolean;
}

/** App-level patient = wire shape + the client-augmented relation/conditions. */
export interface Patient extends PatientDto {
  relation: Relation | null;
  conditions: ConditionCode[];
}

/**
 * Create/update input. `firstName`/`lastName`/`displayName` derive from the A4 single
 * full-name field (split on the first space); `birthDate` derives from the age field.
 * `bloodType`/`initialMedicalNotes` are deferred to the E2 record viewer.
 */
export interface CreatePatientInput {
  displayName: string;
  firstName: string;
  lastName: string;
  birthDate: string;
  gender: Gender;
  bloodType?: string | null;
  initialMedicalNotes?: string | null;
  relation: Relation | null;
  conditions: ConditionCode[];
}

export type UpdatePatientInput = CreatePatientInput;

/** The domain's API seam — a mock and the real client both implement this interface. */
export interface PatientsApi {
  list(params?: PageParams): Promise<Paginated<Patient>>;
  get(id: number): Promise<Patient>;
  create(input: CreatePatientInput): Promise<Patient>;
  update(id: number, input: UpdatePatientInput): Promise<Patient>;
  archive(id: number): Promise<void>;
}
