/**
 * Notification Type Registry
 *
 * The single source of truth for every event the platform can notify about.
 * A caller passes a type and the payload; category, priority, default title and
 * the target module all come from here, so the same event never turns up with
 * two different labels in two different modules.
 *
 * Types are dotted and read `<area>.<subject>.<outcome>`, e.g.
 * `ai.generation.completed`. Adding an event means adding one entry here — the
 * service, API and UI need no change.
 */

import type { NotificationCategory, NotificationPriority } from '../models/Notification';

export interface NotificationTypeDef {
  /** Grouping used for filtering, icons and per-category preferences. */
  category: NotificationCategory;
  /** Default urgency. A caller may override it per event. */
  priority: NotificationPriority;
  /** Sidebar module id this belongs to — drives the module chip and deep links. */
  module: string;
  /** Default title when the caller does not supply one. */
  title: string;
  /**
   * True when the event concerns only the person who caused it (their AI job,
   * their export, their login). The service refuses to fan these out to a role
   * or an organisation — see `notify()`.
   */
  personal?: boolean;
}

export const NOTIFICATION_TYPES = {
  // ── Authentication & account ─────────────────────────────────────────
  'auth.password.reset': { category: 'account', priority: 'high', module: 'account', title: 'Password changed', personal: true },
  'auth.login.new_device': { category: 'account', priority: 'high', module: 'account', title: 'New sign-in to your account', personal: true },
  'auth.account.locked': { category: 'account', priority: 'critical', module: 'account', title: 'Account locked', personal: true },
  'profile.updated': { category: 'account', priority: 'low', module: 'account', title: 'Profile updated', personal: true },

  // ── AI generation ────────────────────────────────────────────────────
  'ai.generation.completed': { category: 'ai', priority: 'normal', module: 'ai-processing', title: 'AI generation completed', personal: true },
  'ai.generation.failed': { category: 'ai', priority: 'high', module: 'ai-processing', title: 'AI generation failed', personal: true },
  'ai.generation.cancelled': { category: 'ai', priority: 'low', module: 'ai-processing', title: 'AI generation cancelled', personal: true },
  'ai.generation.queued': { category: 'ai', priority: 'low', module: 'ai-processing', title: 'AI generation queued', personal: true },

  // ── Feature requests ─────────────────────────────────────────────────
  // Filed under `support`: raising a feature request is the same act as raising
  // a ticket, and the retired `approval` category is where these used to sit.
  'feature_request.created': { category: 'support', priority: 'normal', module: 'request-feature', title: 'New feature request' },
  'feature_request.approved': { category: 'support', priority: 'normal', module: 'request-feature', title: 'Feature request approved' },
  'feature_request.rejected': { category: 'support', priority: 'normal', module: 'request-feature', title: 'Feature request rejected' },
  'feature_request.status_changed': { category: 'support', priority: 'low', module: 'request-feature', title: 'Feature request updated' },
  'feature_request.comment_added': { category: 'support', priority: 'low', module: 'request-feature', title: 'New comment on a feature request' },

  // ── Support ──────────────────────────────────────────────────────────
  'support.ticket.created': { category: 'support', priority: 'normal', module: 'help-support', title: 'New support ticket' },
  'support.ticket.assigned': { category: 'support', priority: 'normal', module: 'help-support', title: 'Ticket assigned to you' },
  'support.ticket.escalated': { category: 'support', priority: 'high', module: 'help-support', title: 'Ticket escalated' },
  'support.ticket.replied': { category: 'support', priority: 'normal', module: 'help-support', title: 'New reply on your ticket' },
  // `normal`, not `low`: low priority is withheld from email as chatter (see
  // resolveChannels), and a resolution is the one support event the customer is
  // waiting for and is least likely to be in the app for — leaving it low made
  // the Support row's Email switch a no-op for exactly that event.
  'support.ticket.resolved': { category: 'support', priority: 'normal', module: 'help-support', title: 'Ticket resolved' },

  // ── Billing & subscription ───────────────────────────────────────────
  'billing.payment.succeeded': { category: 'billing', priority: 'normal', module: 'subscription', title: 'Payment successful' },
  'billing.payment.failed': { category: 'billing', priority: 'critical', module: 'subscription', title: 'Payment failed' },
  'billing.invoice.ready': { category: 'billing', priority: 'normal', module: 'subscription', title: 'Invoice available' },
  'billing.subscription.expiring': { category: 'billing', priority: 'high', module: 'subscription', title: 'Subscription expiring soon' },
  'billing.subscription.expired': { category: 'billing', priority: 'critical', module: 'subscription', title: 'Subscription expired' },
  'billing.subscription.cancelled': { category: 'billing', priority: 'high', module: 'subscription', title: 'Subscription cancelled' },
  'billing.trial.ending': { category: 'billing', priority: 'high', module: 'subscription', title: 'Trial ending soon' },
  'billing.limit.reached': { category: 'billing', priority: 'high', module: 'subscription', title: 'Plan limit reached' },
  'billing.package.updated': { category: 'billing', priority: 'normal', module: 'subscription', title: 'Your plan changed' },

  // ── Users & access ───────────────────────────────────────────────────
  'user.invited': { category: 'account', priority: 'normal', module: 'users', title: 'Team invitation sent' },
  'user.joined': { category: 'account', priority: 'normal', module: 'users', title: 'New team member joined' },
  'user.role_changed': { category: 'account', priority: 'high', module: 'users', title: 'Your access level changed' },
  'user.deactivated': { category: 'account', priority: 'high', module: 'users', title: 'Account deactivated' },
  // Access Control — the role definitions themselves, as opposed to which role a
  // person holds (`user.role_changed`). Changing a role changes what everyone
  // holding it can reach, so it belongs to the same account & access audience.
  'role.created': { category: 'account', priority: 'normal', module: 'access-control', title: 'New role created' },
  'role.updated': { category: 'account', priority: 'normal', module: 'access-control', title: 'Role updated' },
  'role.deleted': { category: 'account', priority: 'high', module: 'access-control', title: 'Role deleted' },

  // ── Content workflow ─────────────────────────────────────────────────
  // The approval events moved here when the `approval` category was retired —
  // a decision on a piece of content is content news, and this keeps one row
  // for everything that happens to it.
  'content.submitted_for_approval': { category: 'content', priority: 'normal', module: 'general', title: 'Content awaiting your approval' },
  'content.approved': { category: 'content', priority: 'normal', module: 'general', title: 'Your content was approved' },
  'content.rejected': { category: 'content', priority: 'high', module: 'general', title: 'Your content needs changes' },
  'content.assigned': { category: 'content', priority: 'normal', module: 'general', title: 'Assigned to you' },

  // ── Campaigns & publishing ───────────────────────────────────────────
  'newsletter.campaign.sent': { category: 'social', priority: 'normal', module: 'newsletter-content-os', title: 'Newsletter sent' },
  'newsletter.campaign.failed': { category: 'social', priority: 'high', module: 'newsletter-content-os', title: 'Newsletter send failed' },
  'social.publish.completed': { category: 'social', priority: 'normal', module: 'social-media-os', title: 'Post published' },
  'social.publish.failed': { category: 'social', priority: 'high', module: 'social-media-os', title: 'Publishing failed' },
  'social.token.expired': { category: 'social', priority: 'high', module: 'social-media-os', title: 'Social account needs reconnecting' },
  'email.dispatch.failed': { category: 'system', priority: 'high', module: 'email-configuration', title: 'Email could not be delivered' },
  'referral.registered': { category: 'account', priority: 'normal', module: 'referral-tracking', title: 'Referral signed up' },
  'referral.converted': { category: 'account', priority: 'normal', module: 'referral-tracking', title: 'Referral converted' },

  // ── Deployments ──────────────────────────────────────────────────────
  // `social` is the Publishing row. A website or landing page going live is
  // publishing in exactly the sense that row now names, so the one switch
  // covers every module that puts something in front of an audience.
  'deploy.completed': { category: 'social', priority: 'normal', module: 'website-planner', title: 'Deployment completed' },
  'deploy.failed': { category: 'social', priority: 'high', module: 'website-planner', title: 'Deployment failed' },

  // ── Data movement ────────────────────────────────────────────────────
  'export.completed': { category: 'system', priority: 'low', module: 'general', title: 'Export ready', personal: true },
  'export.failed': { category: 'system', priority: 'high', module: 'general', title: 'Export failed', personal: true },
  'import.completed': { category: 'system', priority: 'normal', module: 'general', title: 'Import completed', personal: true },
  'import.failed': { category: 'system', priority: 'high', module: 'general', title: 'Import failed', personal: true },
  'backup.completed': { category: 'system', priority: 'low', module: 'backup-restore', title: 'Backup completed' },
  'backup.failed': { category: 'system', priority: 'high', module: 'backup-restore', title: 'Backup failed' },

  // ── Platform health (Super Admin) ────────────────────────────────────
  'system.smtp.failure': { category: 'system', priority: 'critical', module: 'email-configuration', title: 'Email delivery is failing' },
  'system.ai_key.exhausted': { category: 'system', priority: 'critical', module: 'ai-processing', title: 'AI provider key exhausted' },
  'system.gateway.invalid': { category: 'system', priority: 'critical', module: 'payment-gateways', title: 'Payment gateway misconfigured' },
  'system.org.registered': { category: 'system', priority: 'normal', module: 'organizations', title: 'New organisation registered' },
  'system.announcement': { category: 'system', priority: 'normal', module: 'general', title: 'Announcement' },
} as const satisfies Record<string, NotificationTypeDef>;

export type NotificationType = keyof typeof NOTIFICATION_TYPES;

/**
 * Definition for a type. Unknown types resolve to a safe generic entry rather
 * than throwing — a notification must never be the thing that breaks a caller.
 */
export function getNotificationTypeDef(type: string): NotificationTypeDef {
  return (
    (NOTIFICATION_TYPES as Record<string, NotificationTypeDef>)[type] ?? {
      category: 'system',
      priority: 'normal',
      module: 'general',
      title: 'Notification',
    }
  );
}

/** True when a type must only ever reach the person who caused it. */
export function isPersonalType(type: string): boolean {
  return getNotificationTypeDef(type).personal === true;
}
