import { sleep } from '@/utils';
import type { Paginated, PageParams } from '@/lib/api/types';
import { parseNotificationData } from '../parse';
import type { AppNotification, NotificationsApi } from '../types';

/**
 * In-memory `NotificationsApi` — **the primary implementation this phase** (`USE_NOTIFICATIONS_MOCK = true`;
 * nothing dispatches notifications client-side yet — see `constants.ts`).
 *
 * It seeds a realistic **unread-first** feed spanning every deep-link class so `notificationDeepLink` is
 * exercisable end-to-end, keeps a `dataJson` string per row (snake_case, as the contract serves) that the
 * list maps through the real `parseNotificationData`, and exposes a dev-only `__mockPushNotification` so a
 * human can watch the bell badge increment within the poll interval (phase §7 step 4). Booking/ticket/nurse
 * ids align with the f8 bookings + tickets mocks so a deep-link lands on a real screen.
 */

const MOCK_LATENCY_MS = 200;

interface StoredNotification {
  id: number;
  type: string;
  title: string;
  body: string | null;
  dataJson: string | null;
  isRead: boolean;
  createdAt: string;
}

/** ISO instant `mins` in the past — seeded timestamps (rendered Shamsi client-side). */
function isoMinsAgo(mins: number): string {
  return new Date(Date.now() - mins * 60_000).toISOString();
}

let nextNotificationId = 8100;

const notifications: StoredNotification[] = [
  { id: 8001, type: 'ticket_message', title: 'پیام جدید در تیکت', body: 'پرستار به هماهنگی ویزیت شما پاسخ داد.', dataJson: '{"ticket_id":1201}', isRead: false, createdAt: isoMinsAgo(90) },
  { id: 8002, type: 'booking_confirmed', title: 'رزرو شما تایید شد', body: 'ویزیت شما ثبت و تایید شد.', dataJson: '{"booking_id":5001}', isRead: false, createdAt: isoMinsAgo(240) },
  { id: 8003, type: 'refund_processed', title: 'بازپرداخت ثبت شد', body: 'بازپرداخت شما در حال انجام است.', dataJson: '{"booking_id":5004}', isRead: false, createdAt: isoMinsAgo(600) },
  { id: 8004, type: 'payment_captured', title: 'پرداخت انجام شد', body: 'مبلغ ویزیت با موفقیت پرداخت شد.', dataJson: '{"booking_id":5001}', isRead: true, createdAt: isoMinsAgo(1_440) },
  { id: 8005, type: 'payout_paid', title: 'تسویه واریز شد', body: 'درآمد این هفته به حساب شما واریز شد.', dataJson: '{"payout_id":7001}', isRead: true, createdAt: isoMinsAgo(2_880) },
  { id: 8006, type: 'review_published', title: 'نظر شما منتشر شد', body: null, dataJson: '{"nurse_profile_id":1}', isRead: true, createdAt: isoMinsAgo(4_320) },
  // Unknown type + no payload → degrades to no deep-link (still a readable, informational row).
  { id: 8007, type: 'system_message', title: 'به بالین‌یار خوش آمدید', body: 'سلامت خانواده شما، اولویت ماست.', dataJson: null, isRead: true, createdAt: isoMinsAgo(10_080) },
];

function toAppNotification(n: StoredNotification): AppNotification {
  return {
    id: n.id,
    type: n.type,
    title: n.title,
    body: n.body,
    isRead: n.isRead,
    createdAt: n.createdAt,
    data: parseNotificationData(n.type, n.dataJson),
  };
}

/** Unread first, then newest-first (server ordering). */
function ordered(): StoredNotification[] {
  return [...notifications].sort((a, b) => {
    if (a.isRead !== b.isRead) return a.isRead ? 1 : -1;
    return Date.parse(b.createdAt) - Date.parse(a.createdAt);
  });
}

export const notificationsMockApi: NotificationsApi = {
  listNotifications: async (params: PageParams): Promise<Paginated<AppNotification>> => {
    await sleep(MOCK_LATENCY_MS);
    const all = ordered();
    const page = Math.max(1, params.page ?? 1);
    const pageSize = Math.max(1, params.pageSize ?? all.length);
    const start = (page - 1) * pageSize;
    return { items: all.slice(start, start + pageSize).map(toAppNotification), total: all.length, page, pageSize };
  },

  getUnreadCount: async (): Promise<number> => {
    await sleep(MOCK_LATENCY_MS);
    return notifications.filter((n) => !n.isRead).length;
  },

  markRead: async (notificationId: number): Promise<void> => {
    await sleep(MOCK_LATENCY_MS);
    const n = notifications.find((x) => x.id === notificationId);
    if (n) n.isRead = true;
  },

  markAllRead: async (): Promise<void> => {
    await sleep(MOCK_LATENCY_MS);
    notifications.forEach((n) => {
      n.isRead = true;
    });
  },
};

/**
 * DEV-ONLY: simulate a fresh notification arriving so a human can watch the bell badge increment within the
 * poll interval (phase §7 step 4) and open it → deep-link. Prepends an **unread** row. `dataJson` is a
 * snake_case JSON string, exactly as the wire serves it. Call it from the console. Not wired into any screen.
 */
export function __mockPushNotification(
  type: string,
  title: string,
  dataJson: string | null = null,
  body: string | null = null,
): void {
  notifications.unshift({ id: nextNotificationId++, type, title, body, dataJson, isRead: false, createdAt: new Date().toISOString() });
}
