import { clientFetch } from '@/lib/api/client';
import { unwrap, type ApiEnvelope, type Paginated } from '@/lib/api/types';
import { BOOKING_REQUEST_PAGE_SIZE } from '../constants';
import type {
  BookingRequestDto,
  BookingRequestListItem,
  BookingRequestListParams,
  BookingRequestsApi,
  CreateBookingRequestPayload,
  RejectBookingRequestPayload,
} from '../types';

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

/**
 * Real HTTP implementation of the `BookingRequestsApi` seam (b8 contract
 * `dev/contracts/domains/booking-requests.md`). Routes are action-style + snake_case; ids for
 * accept/reject/cancel/get come from the **route**, never the body; JSON bodies/fields are camelCase and
 * `clientFetch` returns the raw envelope, so we `unwrap()`. Mutations use POST.
 *
 * PRIMARY once `USE_BOOKING_REQUESTS_MOCK = false` (refinement-phase-4; REQ-013/014/017 delivered): the
 * DTO now carries `variantPrice` + `nurseAvatarUrl` (REQ-013) + `bookingId` (REQ-017), and the list item
 * carries `variantLabel` + `patientAge` (REQ-014), so the wire maps 1:1 to the app DTO. The `context` arg
 * (a mock-only display aid) is ignored here, and the nurse-view masking is done server-side.
 */
export const bookingRequestsClientApi: BookingRequestsApi = {
  create: async (payload: CreateBookingRequestPayload) =>
    unwrap(
      await clientFetch<ApiEnvelope<BookingRequestDto>>(`${BASE}/create`, {
        method: 'POST',
        body: JSON.stringify(payload),
      }),
    ),

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

  list: async (params: BookingRequestListParams): Promise<Paginated<BookingRequestListItem>> => {
    const query = new URLSearchParams();
    query.set('role', params.role);
    if (params.status) query.set('status', params.status);
    query.set('page', String(params.page ?? 1));
    query.set('pageSize', String(params.pageSize ?? BOOKING_REQUEST_PAGE_SIZE));
    return unwrap(
      await clientFetch<ApiEnvelope<Paginated<BookingRequestListItem>>>(`${BASE}/list?${query.toString()}`),
    );
  },

  accept: async (id: number) =>
    unwrap(await clientFetch<ApiEnvelope<BookingRequestDto>>(`${BASE}/accept/${id}`, { method: 'POST' })),

  reject: async (id: number, payload: RejectBookingRequestPayload) =>
    unwrap(
      await clientFetch<ApiEnvelope<BookingRequestDto>>(`${BASE}/reject/${id}`, {
        method: 'POST',
        body: JSON.stringify(payload),
      }),
    ),

  cancel: async (id: number) =>
    unwrap(await clientFetch<ApiEnvelope<BookingRequestDto>>(`${BASE}/cancel/${id}`, { method: 'POST' })),
};
