export const NOTIFICATION_CHANNELS = [
  'in_app',
  'email',
  'teams',
  'line',
  'slack',
  'mobile_push',
  'sms',
  'web_notification',
  'webhook',
] as const;

export const NOTIFICATION_EVENT_STATUSES = [
  'pending',
  'processed',
  'failed',
] as const;

export const NOTIFICATION_DISPATCH_STATUSES = [
  'pending',
  'sending',
  'sent',
  'failed',
  'retry',
] as const;

export const NOTIFICATION_INBOX_STATUSES = [
  'unread',
  'read',
  'archived',
] as const;

export const NOTIFICATION_BODY_FORMATS = ['plain', 'html'] as const;

export const NOTIFICATION_SEVERITIES = [
  'info',
  'success',
  'warning',
  'error',
] as const;

export type NotificationChannel = (typeof NOTIFICATION_CHANNELS)[number];
export type NotificationEventStatus =
  (typeof NOTIFICATION_EVENT_STATUSES)[number];
export type NotificationDispatchStatus =
  (typeof NOTIFICATION_DISPATCH_STATUSES)[number];
export type NotificationStatus = (typeof NOTIFICATION_INBOX_STATUSES)[number];
export type NotificationBodyFormat =
  (typeof NOTIFICATION_BODY_FORMATS)[number];
export type NotificationSeverity = (typeof NOTIFICATION_SEVERITIES)[number];

export type NotificationTemplateRecord = {
  id: string;
  organizationId: string;
  eventType: string;
  code: string;
  name: string;
  channel: NotificationChannel;
  subjectTemplate: string | null;
  titleTemplate: string;
  bodyTemplate: string;
  bodyFormat: NotificationBodyFormat;
  linkTemplate: string | null;
  language: string;
  variables: string[];
  version: number;
  isActive: boolean;
  metadata: Record<string, unknown> | null;
  createdAt: string;
  updatedAt: string;
  deletedAt: string | null;
  createdBy: string;
  updatedBy: string;
};

export type NotificationEventRecord = {
  id: string;
  organizationId: string;
  eventType: string;
  entityType: string;
  entityId: string;
  actorUserId: string | null;
  payload: Record<string, unknown> | null;
  dedupeKey: string | null;
  status: NotificationEventStatus;
  lastError: string | null;
  publishedAt: string;
  processedAt: string | null;
  createdAt: string;
  updatedAt: string;
};

export type AppNotificationRecord = {
  id: string;
  organizationId: string;
  recipientUserId: string;
  eventId: string;
  title: string;
  body: string;
  linkUrl: string | null;
  severity: NotificationSeverity;
  status: NotificationStatus;
  readAt: string | null;
  archivedAt: string | null;
  metadata: Record<string, unknown> | null;
  createdAt: string;
  updatedAt: string;
};

export type NotificationDispatchRecipient = {
  name?: string | null;
  email: string;
};

export type NotificationAttachmentRef =
  | {
      type: 'artifact';
      artifactId: string;
      label?: string | null;
    }
  | {
      type: 'document_library_version';
      versionId: string;
      label?: string | null;
    }
  | {
      type: 'active_document_library';
      libraryId: string;
      label?: string | null;
    };

export type ResolvedNotificationAttachment = {
  sourceType: NotificationAttachmentRef['type'];
  sourceId: string;
  fileName: string;
  contentType: string;
  size: number;
  checksum: string | null;
  label: string | null;
  buffer: Buffer;
};

export type NotificationDispatchRecord = {
  id: string;
  organizationId: string;
  eventId: string;
  templateId: string | null;
  entityType: string;
  entityId: string;
  channel: NotificationChannel;
  providerKey: string;
  status: NotificationDispatchStatus;
  recipientTo: NotificationDispatchRecipient[];
  recipientCc: NotificationDispatchRecipient[];
  recipientBcc: NotificationDispatchRecipient[];
  replyTo: string | null;
  subject: string;
  bodyText: string;
  bodyHtml: string | null;
  attachments: Array<Omit<ResolvedNotificationAttachment, 'buffer'>>;
  recipientUserId: string | null;
  recipientAddress: string | null;
  requestedBy: string;
  metadata: Record<string, unknown> | null;
  lastError: string | null;
  retryCount: number;
  maxRetryCount: number;
  lastAttemptAt: string | null;
  sentAt: string | null;
  createdAt: string;
  updatedAt: string;
};

export type NotificationRecipientType =
  | 'explicit_user'
  | 'approval_current_step_approvers'
  | 'approval_requester'
  | 'approval_previous_actor'
  | 'entity_owner'
  | 'sales_owner';

export type NotificationRecipientTarget = {
  type: NotificationRecipientType;
  userIds?: string[];
  excludeActor?: boolean;
};

export type PublishNotificationEventInput = {
  organizationId: string;
  eventType: string;
  entityType: string;
  entityId: string;
  actorUserId?: string | null;
  payload?: Record<string, unknown>;
  dedupeKey?: string;
};

export type NotificationListFilters = {
  page?: number;
  limit?: number;
  status?: 'all' | NotificationStatus;
};

export type NotificationHistoryFilters = {
  page?: number;
  limit?: number;
  channel?: NotificationChannel | 'all';
  status?: NotificationDispatchStatus | 'all';
  eventType?: string;
  entityType?: string;
  entityId?: string;
  search?: string;
};

export type NotificationPreviewRequest = {
  organizationId: string;
  actorUserId: string;
  eventType: string;
  entityType: string;
  entityId: string;
  channel: NotificationChannel;
  payload?: Record<string, unknown>;
  templateOverride?: Partial<{
    subjectTemplate: string;
    titleTemplate: string;
    bodyTemplate: string;
    bodyFormat: NotificationBodyFormat;
    linkTemplate: string | null;
  }>;
  recipientOverride: {
    to: NotificationDispatchRecipient[];
    cc?: NotificationDispatchRecipient[];
    bcc?: NotificationDispatchRecipient[];
    replyTo?: string | null;
    recipientUserId?: string | null;
  };
  attachments?: NotificationAttachmentRef[];
  providerKey?: string;
};

export type NotificationSendRequest = NotificationPreviewRequest & {
  maxRetryCount?: number;
};

export type NotificationRenderResult = {
  subject: string;
  title: string;
  bodyText: string;
  bodyHtml: string | null;
  linkUrl: string | null;
  variables: string[];
};

export type NotificationProviderSendInput = {
  dispatchId: string;
  subject: string;
  bodyText: string;
  bodyHtml: string | null;
  to: NotificationDispatchRecipient[];
  cc: NotificationDispatchRecipient[];
  bcc: NotificationDispatchRecipient[];
  replyTo: string | null;
  attachments: Array<Omit<ResolvedNotificationAttachment, 'buffer'>>;
  attachmentBuffers: Buffer[];
};

export type NotificationProviderSendResult = {
  providerMessageId: string | null;
  acceptedRecipients: string[];
  rejectedRecipients: string[];
  metadata?: Record<string, unknown>;
};

export interface NotificationProvider {
  readonly channel: NotificationChannel;
  readonly key: string;
  validate(): Promise<void>;
  healthCheck(): Promise<{ ok: boolean; detail?: string }>;
  send(
    input: NotificationProviderSendInput,
  ): Promise<NotificationProviderSendResult>;
}
