import type { NotificationData } from './types';

/**
 * Parse a notification's wire `data_json` string into the typed `NotificationData` union, keyed off its
 * `type` code. `data_json` is a **typed, versioned contract** (the contract example uses snake_case keys,
 * e.g. `{"booking_id": 1}`), but we read both snake_case and camelCase defensively and **never trust an
 * arbitrary blob**: a malformed JSON string, an unknown `type`, or a missing/invalid id all degrade to
 * `{ kind: 'none' }` (no deep-link) rather than throwing.
 *
 * The many `type` codes collapse to a few deep-link classes so `notificationDeepLink` stays small.
 */
export function parseNotificationData(type: string, dataJson: string | null | undefined): NotificationData {
  const raw = safeParse(dataJson);

  const bookingId = num(raw, 'bookingId', 'booking_id');
  const payoutId = num(raw, 'payoutId', 'payout_id', 'batchId', 'batch_id');
  const ticketId = num(raw, 'ticketId', 'ticket_id');
  const nurseProfileId = num(raw, 'nurseProfileId', 'nurse_profile_id', 'nurseId', 'nurse_id');

  switch (type) {
    case 'booking_confirmed':
    case 'booking_reminder':
    case 'session_reminder':
    case 'payment_captured':
    case 'booking_cancelled':
      return bookingId != null ? { kind: 'booking', bookingId } : { kind: 'none' };

    case 'refund_processed':
    case 'refund_completed':
      // A refund notification deep-links to the booking's refund status (that's how the customer reaches it).
      return bookingId != null ? { kind: 'refund', bookingId } : { kind: 'none' };

    case 'payout_paid':
    case 'payout_failed':
      return payoutId != null ? { kind: 'payout', payoutId } : { kind: 'none' };

    case 'ticket_message':
    case 'ticket_opened':
    case 'ticket_closed':
      return ticketId != null ? { kind: 'ticket', ticketId } : { kind: 'none' };

    case 'review_published':
      return nurseProfileId != null ? { kind: 'nurse_profile', nurseProfileId } : { kind: 'none' };

    default:
      return { kind: 'none' };
  }
}

function safeParse(dataJson: string | null | undefined): Record<string, unknown> {
  if (!dataJson) return {};
  try {
    const parsed: unknown = JSON.parse(dataJson);
    return parsed && typeof parsed === 'object' ? (parsed as Record<string, unknown>) : {};
  } catch {
    return {};
  }
}

/** First key that resolves to a finite number (accepts a numeric string), else `null`. */
function num(obj: Record<string, unknown>, ...keys: string[]): number | null {
  for (const key of keys) {
    const v = obj[key];
    if (typeof v === 'number' && Number.isFinite(v)) return v;
    if (typeof v === 'string' && v.trim() !== '' && Number.isFinite(Number(v))) return Number(v);
  }
  return null;
}
