import { sleep } from '@/utils';
import { ApiError } from '@/lib/api/errors';
import type { PageParams, Paginated } from '@/lib/api/types';
import type { CreatePatientInput, Patient, PatientsApi } from '../types';

const MOCK_LATENCY_MS = 350;

// In-memory store, seeded **empty** so a single session can demo both the onboarding flow
// (A3→A4 creates the first patient) and the E1 empty state. Archive is soft (isActive=false)
// and never removes the row — the list simply hides inactive patients.
let store: Patient[] = [];
let nextId = 1;

function build(id: number, input: CreatePatientInput, isActive: boolean): Patient {
  return {
    id,
    displayName: input.displayName,
    firstName: input.firstName,
    lastName: input.lastName,
    birthDate: input.birthDate,
    gender: input.gender,
    bloodType: input.bloodType ?? null,
    initialMedicalNotes: input.initialMedicalNotes ?? null,
    isActive,
    relation: input.relation,
    conditions: input.conditions,
  };
}

/**
 * In-memory mock behind the PatientsApi seam — the b3 endpoints are live but the wire shape
 * lacks relation/conditions (REQ-005), so this drives the UI until those land. Mirrors the
 * real shapes so swapping is a one-line change in constants.ts.
 */
export const patientsMockApi: PatientsApi = {
  list: async (params?: PageParams): Promise<Paginated<Patient>> => {
    await sleep(MOCK_LATENCY_MS);
    const active = store.filter((patient) => patient.isActive);
    const page = params?.page ?? 1;
    const pageSize = params?.pageSize ?? 50;
    const start = (page - 1) * pageSize;
    return { items: active.slice(start, start + pageSize), total: active.length, page, pageSize };
  },

  get: async (id: number): Promise<Patient> => {
    await sleep(MOCK_LATENCY_MS);
    const found = store.find((patient) => patient.id === id && patient.isActive);
    if (!found) throw new ApiError(404, 'Patient not found');
    return found;
  },

  create: async (input: CreatePatientInput): Promise<Patient> => {
    await sleep(MOCK_LATENCY_MS);
    const patient = build(nextId++, input, true);
    store = [patient, ...store];
    return patient;
  },

  update: async (id: number, input: CreatePatientInput): Promise<Patient> => {
    await sleep(MOCK_LATENCY_MS);
    const existing = store.find((patient) => patient.id === id);
    if (!existing) throw new ApiError(404, 'Patient not found');
    const updated = build(id, input, existing.isActive);
    store = store.map((patient) => (patient.id === id ? updated : patient));
    return updated;
  },

  archive: async (id: number): Promise<void> => {
    await sleep(MOCK_LATENCY_MS);
    store = store.map((patient) => (patient.id === id ? { ...patient, isActive: false } : patient));
  },
};
