import type { AuthPlatform } from "./auth";

const API_BASE = import.meta.env.VITE_API_URL ?? "/api";

export type NotificationType =
  | "DOCUMENT_UPLOADED"
  | "DOCUMENT_PROCESSING"
  | "DOCUMENT_READY"
  | "DOCUMENT_NEEDS_REVIEW"
  | "ACCOUNTANT_QUESTION"
  | "QUESTION_ANSWERED"
  | "QUESTION_RESOLVED"
  | "FIRM_QUERY_REPLY"
  | "INVOICE_APPROVED"
  | "INVOICE_REJECTED"
  | "SNLSTART_SYNC_SUCCESS"
  | "SNLSTART_SYNC_FAILED"
  | "CLIENT_REMINDER"
  | "FINANCIAL_REPORT_READY"
  | "AI_ADVICE_REQUIRES_APPROVAL"
  | string;

export interface AppNotification {
  id: number;
  recipient_platform: string;
  client_id?: string | null;
  type: NotificationType;
  title: string;
  message: string;
  reference_type?: string | null;
  reference_id?: string | null;
  priority: string;
  channel: string;
  is_read: boolean;
  created_at: string;
  read_at?: string | null;
}

export interface NotificationListResponse {
  items: AppNotification[];
  unread_count: number;
  total: number;
}

function identityParams(platform: AuthPlatform, email: string, clientId?: string) {
  const params = new URLSearchParams({
    platform,
    email: email.trim().toLowerCase(),
  });
  if (platform === "client" && clientId) {
    params.set("client_id", clientId);
  }
  return params;
}

function identityBody(platform: AuthPlatform, email: string, clientId?: string) {
  return {
    platform,
    email: email.trim().toLowerCase(),
    ...(platform === "client" && clientId ? { client_id: clientId } : {}),
  };
}

async function request<T>(path: string, init?: RequestInit): Promise<T> {
  const response = await fetch(`${API_BASE}${path}`, {
    headers: {
      "Content-Type": "application/json",
      ...(init?.headers ?? {}),
    },
    ...init,
  });
  if (!response.ok) {
    const message = await response.text();
    throw new Error(message || `Request failed: ${response.status}`);
  }
  return (await response.json()) as T;
}

export function fetchNotifications(
  platform: AuthPlatform,
  email: string,
  opts?: { clientId?: string; unreadOnly?: boolean; limit?: number; offset?: number },
) {
  const params = identityParams(platform, email, opts?.clientId);
  if (opts?.unreadOnly) params.set("unread_only", "true");
  if (opts?.limit != null) params.set("limit", String(opts.limit));
  if (opts?.offset != null) params.set("offset", String(opts.offset));
  return request<NotificationListResponse>(`/notifications?${params.toString()}`);
}

export function fetchUnreadCount(platform: AuthPlatform, email: string, clientId?: string) {
  const params = identityParams(platform, email, clientId);
  return request<{ unread_count: number }>(`/notifications/unread-count?${params.toString()}`);
}

export function markNotificationRead(
  platform: AuthPlatform,
  email: string,
  id: number,
  clientId?: string,
) {
  return request<AppNotification>(`/notifications/${id}/read`, {
    method: "POST",
    body: JSON.stringify(identityBody(platform, email, clientId)),
  });
}

export function markAllNotificationsRead(platform: AuthPlatform, email: string, clientId?: string) {
  return request<{ ok: boolean; updated: number }>("/notifications/read-all", {
    method: "POST",
    body: JSON.stringify(identityBody(platform, email, clientId)),
  });
}

/** Deep-link target for a notification within the current portal. */
export function notificationNavigation(
  platform: AuthPlatform,
  n: AppNotification,
): { to: string; params?: Record<string, string> } {
  const ref = n.reference_type;
  const id = n.reference_id;

  if (platform === "firm") {
    if (ref === "invoice" && id) return { to: "/invoices/$id", params: { id } };
    if (ref === "query" && id) return { to: "/queries/$id", params: { id } };
    return { to: "/notifications" };
  }

  if (ref === "invoice" && id) return { to: "/documents/$id", params: { id } };
  if (ref === "query" && id) return { to: "/queries/$id", params: { id } };
  return { to: "/notifications" };
}

/** @deprecated use notificationNavigation */
export function notificationHref(platform: AuthPlatform, n: AppNotification): string {
  const nav = notificationNavigation(platform, n);
  if (nav.params?.id) return nav.to.replace("$id", nav.params.id);
  return nav.to;
}

export function notificationRelativeTime(iso: string): string {
  const ts = Date.parse(iso);
  if (Number.isNaN(ts)) return iso;
  const diff = Date.now() - ts;
  const mins = Math.floor(diff / 60000);
  if (mins < 1) return "Just now";
  if (mins < 60) return `${mins} minute${mins === 1 ? "" : "s"} ago`;
  const hours = Math.floor(mins / 60);
  if (hours < 24) return `${hours} hour${hours === 1 ? "" : "s"} ago`;
  const days = Math.floor(hours / 24);
  if (days === 1) return "Yesterday";
  if (days < 7) return `${days} days ago`;
  return new Date(ts).toLocaleDateString("en-GB", { day: "numeric", month: "short" });
}
