import { clientFetch } from '@/lib/api/client';
import { unwrap, type ApiEnvelope, type Paginated } from '@/lib/api/types';
import type {
  ConditionCode,
  CreatePatientInput,
  Patient,
  PatientDto,
  PatientsApi,
  Relation,
} from '../types';

const BASE = '/api/v1/patients';

/** REQ-005 (delivered): the wire `PatientDto` now carries `relation`/`conditions` (both nullable). */
interface PatientWire extends PatientDto {
  relation: Relation | null;
  conditions: ConditionCode[] | null;
}

function toPatient(dto: PatientWire): Patient {
  return { ...dto, relation: dto.relation ?? null, conditions: dto.conditions ?? [] };
}

// REQ-005 (delivered): relation/conditions now cross the wire and are persisted server-side.
function toBody(input: CreatePatientInput) {
  const { displayName, firstName, lastName, birthDate, gender } = input;
  return {
    displayName,
    firstName,
    lastName,
    birthDate,
    gender,
    bloodType: input.bloodType ?? null,
    initialMedicalNotes: input.initialMedicalNotes ?? null,
    relation: input.relation,
    conditions: input.conditions,
  };
}

/**
 * Real HTTP implementation of the PatientsApi seam (b3 action-style routes). `clientFetch`
 * returns the raw envelope, so each call reads its payload via `unwrap`. Primary once
 * USE_PATIENTS_MOCK is false (refinement-phase-4; REQ-005 delivered).
 */
export const patientsClientApi: PatientsApi = {
  list: async (params) => {
    const query = new URLSearchParams();
    if (params?.page) query.set('page', String(params.page));
    if (params?.pageSize) query.set('pageSize', String(params.pageSize));
    const qs = query.toString();
    const page = unwrap(await clientFetch<ApiEnvelope<Paginated<PatientWire>>>(`${BASE}/list${qs ? `?${qs}` : ''}`));
    return { ...page, items: page.items.map((dto) => toPatient(dto)) };
  },

  get: async (id) => toPatient(unwrap(await clientFetch<ApiEnvelope<PatientWire>>(`${BASE}/get/${id}`))),

  create: async (input) =>
    toPatient(
      unwrap(
        await clientFetch<ApiEnvelope<PatientWire>>(`${BASE}/create`, {
          method: 'POST',
          body: JSON.stringify(toBody(input)),
        }),
      ),
    ),

  update: async (id, input) =>
    toPatient(
      unwrap(
        await clientFetch<ApiEnvelope<PatientWire>>(`${BASE}/update/${id}`, {
          method: 'POST',
          body: JSON.stringify(toBody(input)),
        }),
      ),
    ),

  archive: async (id) => {
    await clientFetch<ApiEnvelope<void>>(`${BASE}/archive/${id}`, { method: 'POST' });
  },
};
