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

/**
 * Notifications domain — the app's **pull** mechanism (b1). In-app only (no push at launch), **polled**, with
 * a typed `data_json` payload that tells the front-end where to deep-link. 90-day read retention is a server
 * concern. Shapes derive from the b1 contract (`config-reference.md` → `NotificationDto`; swagger
 * `NotificationDto`/`UnreadCountResult`/`MarkNotificationReadCommand`).
 *
 * **Load-bearing rules (phase §5):**
 *  - **`data_json` is a typed contract** — parse it into the discriminated `NotificationData` union and
 *    deep-link off that; never `eval`/trust an arbitrary blob, and degrade gracefully (no deep-link) for an
 *    unknown `type` or a missing id.
 *  - **Poll the count politely** — only `useUnreadCount` polls (stale-while-revalidate); the list is not
 *    polled on an interval.
 *  - **Tenancy** — every read is scoped to the signed-in caller server-side; never fetch by a raw id.
 */

/**
 * The parsed deep-link target of a notification, discriminated by `kind`. The many notification `type` codes
 * collapse to a few route classes here (a booking, a refund view, a payout, a ticket, a nurse profile), or
 * `none` when there's nothing to open. Parsed from `data_json` by `parseNotificationData`.
 */
export type NotificationData =
  | { kind: 'booking'; bookingId: number }
  | { kind: 'refund'; bookingId: number }
  | { kind: 'payout'; payoutId: number }
  | { kind: 'ticket'; ticketId: number }
  | { kind: 'nurse_profile'; nurseProfileId: number }
  | { kind: 'none' };

/** A client notification (`NotificationDto` + the parsed `data`). `type`/`title`/`body` are server-rendered. */
export interface AppNotification {
  id: number;
  /** Open string code (e.g. `booking_confirmed`) — the server owns the copy; we deep-link off `data`. */
  type: string;
  title: string;
  body: string | null;
  isRead: boolean;
  /** UTC ISO-8601 — Shamsi display is the client's job. */
  createdAt: string;
  /** Parsed from the wire `dataJson` string into the typed union (never the raw blob). */
  data: NotificationData;
}

/**
 * The notifications API seam — the real HTTP client and the in-memory mock both implement this; selection is
 * by config (`USE_NOTIFICATIONS_MOCK`). Reads are tenant-scoped server-side.
 */
export interface NotificationsApi {
  /** Paged, **unread-first then newest-first** (server ordering). */
  listNotifications(params: PageParams): Promise<Paginated<AppNotification>>;
  /** Cheap index-backed count for the polling bell. */
  getUnreadCount(): Promise<number>;
  markRead(notificationId: number): Promise<void>;
  markAllRead(): Promise<void>;
}
