/**
 * Shared contracts for the freight in-app notification system.
 *
 * The notification *mechanism* (module, gateway, bell) ships first; individual
 * domain triggers are wired later. The `NotificationType` values below seed the
 * intended trigger set so the frontend can map icons/labels before any producer
 * actually emits them.
 */

/** Which app surface a notification is addressed to. */
export enum NotificationAudience {
  PORTAL = "PORTAL",
  BACKOFFICE = "BACKOFFICE",
}

/**
 * Default channel fan-out when {@link NotifyInput.channels} is not given:
 * HIGH also pushes email/SMS, NORMAL is in-app only. An explicit `channels`
 * selection overrides this.
 */
export enum NotificationPriority {
  NORMAL = "NORMAL",
  HIGH = "HIGH",
}

/**
 * Semantic type of a notification. Used by the frontend to pick an icon/label
 * and by producers to categorize. `GENERIC` is the catch-all for ad-hoc calls.
 */
export enum NotificationType {
  GENERIC = "GENERIC",
  // Portal-facing (customer)
  ACCOUNT_STATUS = "ACCOUNT_STATUS",
  CLEARANCE_DECISION = "CLEARANCE_DECISION",
  DOCUMENT_ACTION = "DOCUMENT_ACTION",
  BOOKING_STATUS = "BOOKING_STATUS",
  CONTRACT_STATUS = "CONTRACT_STATUS",
  SCHEDULE_UPDATE = "SCHEDULE_UPDATE",
  INVOICE_ISSUED = "INVOICE_ISSUED",
  // Backoffice-facing (staff)
  REQUEST_SUBMITTED = "REQUEST_SUBMITTED",
  PAYMENT_RECEIVED = "PAYMENT_RECEIVED",
  CLEARANCE_REVIEW = "CLEARANCE_REVIEW",
}

/**
 * Explicit fan-out channel selection for a single `notify(...)` call.
 *
 * In-app delivery is always performed (this module is an inbox) and is not
 * listed here. These flags control the *extra* outbound channels. When omitted
 * on {@link NotifyInput}, channels fall back to priority: HIGH ⇒ email + SMS,
 * NORMAL ⇒ none.
 */
export interface NotificationChannels {
  email?: boolean;
  sms?: boolean;
}

/** Optional per-channel delivery outcome recorded on the notification row. */
export interface NotificationChannelsSent {
  email?: boolean;
  sms?: boolean;
}

/** A persisted in-app notification as returned to the client. */
export interface NotificationDto {
  id: string;
  recipientUserId: string;
  audience: NotificationAudience;
  type: NotificationType;
  title: string;
  body: string;
  /** Deep-link path within the app the item points to (e.g. `/contracts/:id`). */
  link?: string | null;
  /** Arbitrary structured payload (bookingId, invoiceId, contractId, …). */
  data?: Record<string, unknown> | null;
  priority: NotificationPriority;
  isRead: boolean;
  readAt?: string | null;
  createdAt: string;
}

/** Target selector: any combination resolves to a set of recipient user ids. */
export interface NotificationRecipients {
  /** Explicit IAM user ids — always honored. */
  userIds?: string[];
  /** Portal: all users linked to this company (via external profiles). */
  companyId?: string;
  /** Portal: resolved to the company, then to that company's users. */
  companyProfileId?: string;
  /** Backoffice: all current employees of this organization. */
  organizationId?: string;
  /** Backoffice: every current employee across all organizations. */
  allBackoffice?: boolean;
}

/** Input any subsystem passes to `NotificationInboxService.notify(...)`. */
export interface NotifyInput {
  recipients: NotificationRecipients;
  audience: NotificationAudience;
  type: NotificationType;
  title: string;
  body: string;
  link?: string | null;
  data?: Record<string, unknown> | null;
  priority?: NotificationPriority;
  /**
   * Explicit email/SMS fan-out. Overrides the priority-based default when set;
   * omit to let `priority` decide (HIGH ⇒ email + SMS, NORMAL ⇒ in-app only).
   * In-app is always delivered regardless.
   */
  channels?: NotificationChannels;
}

/** Paginated list envelope for the notifications list endpoint. */
export interface NotificationListResult {
  items: NotificationDto[];
  count: number;
  unreadCount: number;
}

/** Socket.io event names pushed server → client on the `notifications` namespace. */
export const NOTIFICATION_WS_EVENTS = {
  NEW: "notification:new",
  UNREAD_COUNT: "notification:unread-count",
} as const;

/** Socket.io namespace the notifications gateway listens on. */
export const NOTIFICATION_WS_NAMESPACE = "notifications";
