/**
 * Resolve the empty-state onboarding-card icon from a backend
 * `SlashCommandSummary.iconName`.
 *
 * Primary keys match the production `/api/docs/commands` contract
 * (multi-platform-hub) — short, source-system-style identifiers:
 *
 *   - `clickup` → ClickUp brand glyph (mono grey)
 *   - `slack`   → Slack brand glyph (mono grey)
 *   - `hubspot` → HubSpot brand glyph (mono grey)
 *   - `github`  → GitHub brand glyph
 *   - `openframe` → OpenFrame logo
 *   - `newspaper` / `rocket` / `briefcase` / `graduation-cap`
 *     / `video` / `calendar` / `headphones` → v2 generic glyphs
 *     mapped to the closest available icon in `icons-v2-generated`
 *
 * Figma-canonical keys (`clickup-logo-grey`, `logo-openframe`,
 * `rocket-02`, …) and a handful of generic v2 fall-throughs
 * (`search`, `ticket`, `bug`, …) are kept as aliases so the
 * Storybook fixtures and any older feed entries still resolve.
 *
 * Any `iconName` NOT in the curated map below is resolved generically
 * against the entire `icons-v2-generated` set by naming convention
 * (`chart-pie` → `ChartPieIcon`, `bank` → `BankIcon`, …) — see
 * `resolveFromLibrary`. So the full icon library is supported, and the
 * curated map only exists for aliases that don't map 1:1. Keys that
 * name no real icon (and `null`) fall back to `FileIcon` so a
 * misconfigured row still renders.
 */

import type { ComponentType, CSSProperties } from 'react'

import { getIconComponent } from './icon-registry'
import * as IconsV2 from '../../icons-v2-generated'
import { ClickupLogoGreyIcon } from '../../icons-v2-generated/brand-logos/clickup-logo-grey-icon'
import { GithubIcon } from '../../icons-v2-generated/brand-logos/github-icon'
import { HubspotLogoGreyIcon } from '../../icons-v2-generated/brand-logos/hubspot-logo-grey-icon'
import { SlackLogoGreyIcon } from '../../icons-v2-generated/brand-logos/slack-logo-grey-icon'
import { ChatsIcon } from '../../icons-v2-generated/communication/chats-icon'
import { BookIcon } from '../../icons-v2-generated/school/book-icon'
import { GraduationCapIcon } from '../../icons-v2-generated/school/graduation-cap-icon'
import { BracketCurlyIcon } from '../../icons-v2-generated/coding/bracket-curly-icon'
import { BugIcon } from '../../icons-v2-generated/coding/bug-icon'
import { CalendarIcon } from '../../icons-v2-generated/date-and-time/calendar-icon'
import { BriefcaseIcon } from '../../icons-v2-generated/map-and-travel/briefcase-icon'
import { CompassIcon } from '../../icons-v2-generated/map-and-travel/compass-icon'
import { FileIcon } from '../../icons-v2-generated/documents/file-icon'
import { LayersIcon } from '../../icons-v2-generated/design/layers-icon'
import { NewspaperIcon } from '../../icons-v2-generated/documents/newspaper-icon'
import { Rocket02Icon } from '../../icons-v2-generated/vehicles-and-delivery/rocket-02-icon'
import { HeadphoneIcon } from '../../icons-v2-generated/audio-and-visual/headphone-icon'
import { VideoRecorderIcon } from '../../icons-v2-generated/audio-and-visual/video-recorder-icon'
import { SearchIcon } from '../../icons-v2-generated/interface/search-icon'
import { TicketIcon } from '../../icons-v2-generated/shopping/ticket-icon'
import { OpenFrameLogo } from '../../icons/openframe-logo'
import { OpenmspLogo } from '../../icons/openmsp-logo'
import { FlamingoLogo } from '../../icons/flamingo-logo'
import { Megaphone, Bell, Info, Star, Package as PackageGlyph } from 'lucide-react'

/** Shape used by every icon registered here (matches `icons-v2-generated`). */
export type IconComponent = ComponentType<{
  size?: number
  className?: string
  color?: string
}>

/** Wrap a brand logo (className/SVG-sized) so it satisfies the `size`-prop
 *  `IconComponent` contract — drives size via `style` (CSS wins over
 *  the logo's hardcoded width/height), keeping the logo's own brand fill. */
function sizedLogo(
  Logo: ComponentType<{ className?: string; style?: CSSProperties }>,
): IconComponent {
  return function SizedLogo({ size = 16, className }) {
    return <Logo className={className} style={{ width: size, height: size }} />
  }
}
const OpenmspLogoIcon = sizedLogo(OpenmspLogo)
const FlamingoLogoIcon = sizedLogo(FlamingoLogo)

/**
 * `OpenFrameLogo` from `components/icons/` predates the v2 set and:
 *   1. hardcodes `width="32" height="32"` AFTER spreading `{...props}`,
 *      so we can't override via the `width` / `height` props — we drive
 *      size through `style` instead (CSS attribute wins over the HTML
 *      `width` / `height` attributes).
 *   2. defaults `lowerPathColor` to white and `upperPathColor` to
 *      `#1A1A1A` — the dark frame disappears on the chat's `ods-bg`
 *      surface. We pin both paths to `currentColor` so the glyph tints
 *      to whatever the card icon slot is (`ods-text-secondary` ≈ #888).
 */
function LogoOpenframeIcon({
  size = 16,
  className,
  color,
}: {
  size?: number
  className?: string
  color?: string
}) {
  // Forward `color` (from `icon_props.color`) like every other resolver-backed
  // glyph; default to `currentColor` so the logo tints to its slot.
  const tint = color ?? 'currentColor'
  return (
    <OpenFrameLogo
      className={className}
      lowerPathColor={tint}
      upperPathColor={tint}
      style={{ width: size, height: size }}
    />
  )
}

/**
 * Static registry — backend `iconName` → React component. Brand-grey
 * logos live in `icons-v2-generated/brand-logos/`; the rest are
 * monochrome v2 glyphs that inherit `currentColor` from the card slot
 * (`text-ods-text-secondary`).
 */
export const ICON_ALIASES: Record<string, IconComponent> = {
  // Production `/api/docs/commands` keys (multi-platform-hub contract)
  clickup: ClickupLogoGreyIcon,
  slack: SlackLogoGreyIcon,
  hubspot: HubspotLogoGreyIcon,
  github: GithubIcon,
  openframe: LogoOpenframeIcon,
  newspaper: NewspaperIcon,
  rocket: Rocket02Icon,
  briefcase: BriefcaseIcon,
  'graduation-cap': GraduationCapIcon,
  video: VideoRecorderIcon,
  headphones: HeadphoneIcon,
  calendar: CalendarIcon,
  compass: CompassIcon,

  // Figma-canonical aliases (node 7363:205938) — kept for Storybook
  // fixtures and any older feed entries still using the long names.
  'clickup-logo': ClickupLogoGreyIcon,
  'clickup-logo-grey': ClickupLogoGreyIcon,
  'slack-logo': SlackLogoGreyIcon,
  'slack-logo-grey': SlackLogoGreyIcon,
  'hubspot-logo': HubspotLogoGreyIcon,
  'hubspot-logo-grey': HubspotLogoGreyIcon,
  'github-logo': GithubIcon,
  'logo-openframe': LogoOpenframeIcon,
  'rocket-01': Rocket02Icon,
  'rocket-02': Rocket02Icon,

  // Announcement-bar legacy names — folded in so resolveIcon covers them too
  // (was the separate `renderSvgIcon` map; now ONE resolver everywhere).
  'openframe-logo': LogoOpenframeIcon,
  'openmsp-logo': OpenmspLogoIcon,
  flamingo: FlamingoLogoIcon,
  'flamingo-logo': FlamingoLogoIcon,
  megaphone: Megaphone,
  bell: Bell,
  info: Info,
  star: Star,
  package: PackageGlyph,

  // Generic v2-native keys — useful fall-throughs for slash commands that
  // don't have a brand-specific glyph in the design.
  search: SearchIcon,
  ticket: TicketIcon,
  book: BookIcon,
  'book-open': BookIcon,
  bug: BugIcon,
  layers: LayersIcon,
  file: FileIcon,
  'file-text': FileIcon,
  chats: ChatsIcon,
  'message-square': ChatsIcon,
  'message-circle': ChatsIcon,
  'bracket-curly': BracketCurlyIcon,
}

/**
 * Generic resolution against the FULL `icons-v2-generated` set.
 *
 * Every generated icon follows one naming convention: a file named
 * `<kebab>-icon.tsx` exports a component `<PascalCase>Icon` with the
 * `{ size, className, color }` signature `IconComponent`
 * expects. So any backend `iconName` that names a real icon (e.g.
 * `chart-pie`, `bank`, `money-bill-dollar`, `piggy-bank`) resolves
 * here without a hand-maintained entry — the whole library is
 * supported, not just the curated aliases above.
 *
 * Two candidate PascalCase spellings are tried because the generator
 * is inconsistent about the `ai` token: the standalone AI glyphs
 * export `…AIIcon` (`BrainAIIcon`, `CodeAIIcon`), while the Adobe
 * Illustrator brand glyph keeps `AdobeAiIcon`. We try the literal
 * capitalization first, then the `ai → AI` variant, and take whichever
 * actually exists in the namespace (the namespace is the source of
 * truth, so we never guess wrong).
 */
function resolveFromLibrary(
  iconName: string,
): IconComponent | undefined {
  const tokens = iconName.trim().toLowerCase().replace(/_/g, '-').split('-')
  if (tokens.some((t) => t.length === 0)) return undefined
  const cap = (t: string) => t.charAt(0).toUpperCase() + t.slice(1)
  const candidates = [
    `${tokens.map(cap).join('')}Icon`,
    `${tokens.map((t) => (t === 'ai' ? 'AI' : cap(t))).join('')}Icon`,
  ]
  const registry = IconsV2 as unknown as Record<string, IconComponent | undefined>
  for (const name of candidates) {
    const Icon = registry[name]
    if (Icon) return Icon
  }
  return undefined
}

/**
 * THE single icon-name → component resolver for the whole app. Two variants —
 * one entry point, no duplicated resolver machinery:
 *
 *   • `'design'` (DEFAULT): the icons-v2 design set — chat chips, slash
 *      autocomplete, announcement bar, AI-agent icons, the admin picker.
 *      Order: curated `ICON_ALIASES` (brand-grey logos, tinted OpenFrame,
 *      semantic aliases) → generic `icons-v2-generated` by naming convention →
 *      `FileIcon`.
 *   • `'brand'`: the brand/social set (lucide + brand-colored logos) via the
 *      registry resolver `getIconComponent` (PascalCase-normalised) — social
 *      links, source-row CTAs.
 *
 * The two glyph SETS differ on purpose (a grey design 'slack' vs a brand-color
 * social 'slack'); this resolver is the ONE place that owns both. `getIconComponent`
 * / `getDynamicIcon` remain as the brand-variant + sized-brand helpers.
 */
export function resolveIcon(
  iconName: string | null | undefined,
  opts?: { variant?: 'design' | 'brand' },
): IconComponent {
  if (opts?.variant === 'brand') {
    // Brand variant — delegate to the registry resolver (same glyph as before).
    return getIconComponent(iconName) as IconComponent
  }
  if (!iconName) return FileIcon
  return ICON_ALIASES[iconName] ?? resolveFromLibrary(iconName) ?? FileIcon
}

/** One selectable icon in the admin slash-command picker. */
export interface IconOption {
  /** Stored `icon_name` value — a kebab-case `icons-v2-generated` key (or a
   *  curated alias) that `resolveIcon` displays in the chat. */
  key: string
  /** Human-friendly label shown in the picker dropdown. */
  label: string
}

/**
 * Curated icon set offered by the admin slash-command icon picker
 * (`/admin/chat-config` → Edit slash command).
 *
 * THE PICKER AND THE CHAT SHARE ONE ICON SOURCE: every `key` here is an
 * `icons-v2-generated` name (or curated alias) that `resolveIcon`
 * renders — so whatever the admin selects always displays in the chip /
 * autocomplete, with no fallback-glyph drift. (The full library is far larger
 * and resolvable generically; this is the curated, slash-command-relevant
 * subset for a usable dropdown.) Keep keys kebab-case to match the DB
 * `chat_admin_slash_commands.icon_name` convention.
 */
export const ICON_OPTIONS: ReadonlyArray<IconOption> = [
  // Brands
  { key: 'openframe', label: 'OpenFrame' },
  { key: 'slack', label: 'Slack' },
  { key: 'hubspot', label: 'HubSpot' },
  { key: 'clickup', label: 'ClickUp' },
  { key: 'github', label: 'GitHub' },
  { key: 'linkedin', label: 'LinkedIn' },
  { key: 'twitter', label: 'Twitter (X)' },
  { key: 'twitter-x', label: 'X' },
  { key: 'facebook', label: 'Facebook' },
  { key: 'instagram', label: 'Instagram' },
  { key: 'youtube', label: 'YouTube' },
  { key: 'discord', label: 'Discord' },
  { key: 'figma', label: 'Figma' },
  { key: 'google', label: 'Google' },
  { key: 'apple', label: 'Apple' },
  { key: 'windows', label: 'Windows' },
  { key: 'android', label: 'Android' },
  { key: 'openai-logo', label: 'OpenAI' },
  { key: 'anthropic-logo', label: 'Anthropic' },
  // Content & docs
  { key: 'newspaper', label: 'Newspaper' },
  { key: 'book', label: 'Book' },
  { key: 'file', label: 'File' },
  { key: 'file-text', label: 'Document' },
  { key: 'file-code', label: 'Code file' },
  { key: 'file-chart-bar', label: 'Report' },
  { key: 'file-dollar', label: 'Invoice file' },
  { key: 'folder', label: 'Folder' },
  { key: 'folder-open', label: 'Folder open' },
  { key: 'clipboard', label: 'Clipboard' },
  { key: 'clipboard-list', label: 'Checklist' },
  { key: 'clipboard-check', label: 'Clipboard check' },
  { key: 'memo', label: 'Memo' },
  { key: 'paperclip', label: 'Attachment' },
  { key: 'copy-01', label: 'Copy' },
  { key: 'files', label: 'Files' },
  { key: 'box-archive', label: 'Box' },
  { key: 'parcel-01', label: 'Parcel' },
  // Media
  { key: 'video', label: 'Video' },
  { key: 'headphones', label: 'Podcast / audio' },
  { key: 'podcast', label: 'Podcast' },
  { key: 'mic', label: 'Microphone' },
  { key: 'music-note-01', label: 'Music' },
  { key: 'camera', label: 'Camera' },
  { key: 'image', label: 'Image' },
  { key: 'film-hr', label: 'Film' },
  { key: 'play', label: 'Play' },
  // Date & time
  { key: 'calendar', label: 'Calendar' },
  { key: 'calendar-check', label: 'Calendar check' },
  { key: 'clock', label: 'Clock' },
  { key: 'alarm', label: 'Alarm' },
  { key: 'stopwatch', label: 'Stopwatch' },
  { key: 'timer', label: 'Timer' },
  { key: 'hourglass', label: 'Hourglass' },
  // Places & business
  { key: 'briefcase', label: 'Briefcase' },
  { key: 'graduation-cap', label: 'Education' },
  { key: 'building', label: 'Building' },
  { key: 'buildings', label: 'Buildings' },
  { key: 'hospital', label: 'Hospital' },
  { key: 'school', label: 'School' },
  { key: 'warehouse', label: 'Warehouse' },
  { key: 'shop', label: 'Shop' },
  // Communication
  { key: 'search', label: 'Search' },
  { key: 'chats', label: 'Chat' },
  { key: 'message-text', label: 'Message' },
  { key: 'messages', label: 'Messages' },
  { key: 'email', label: 'Email' },
  { key: 'inbox', label: 'Inbox' },
  { key: 'send-01', label: 'Send' },
  { key: 'at-sign', label: 'Mention' },
  { key: 'bell', label: 'Notifications' },
  { key: 'megaphone-01', label: 'Announcement' },
  // Charts & analytics
  { key: 'chart-pie', label: 'Pie chart' },
  { key: 'chart-donut', label: 'Donut chart' },
  { key: 'chart-bar-01-ver', label: 'Bar chart' },
  { key: 'chart-line-up', label: 'Line chart' },
  { key: 'trend-up', label: 'Trend up' },
  { key: 'trend-down', label: 'Trend down' },
  { key: 'presentation', label: 'Presentation' },
  { key: 'analysis', label: 'Analysis' },
  { key: 'activity', label: 'Activity' },
  { key: 'network', label: 'Network' },
  // Finance
  { key: 'bank', label: 'Bank' },
  { key: 'money-bill-dollar', label: 'Money' },
  { key: 'money-bill', label: 'Bill' },
  { key: 'coins', label: 'Coins' },
  { key: 'coin', label: 'Coin' },
  { key: 'coins-exchange-currency', label: 'Currency exchange' },
  { key: 'piggy-bank', label: 'Savings' },
  { key: 'wallet-01', label: 'Wallet' },
  { key: 'credit-card', label: 'Credit card' },
  { key: 'hand-coin', label: 'Hand coin' },
  { key: 'dollar', label: 'Dollar' },
  { key: 'dollar-circle', label: 'Dollar circle' },
  { key: 'euro', label: 'Euro' },
  { key: 'bitcoin', label: 'Bitcoin' },
  { key: 'percent', label: 'Percent' },
  { key: 'receipt-01', label: 'Receipt' },
  { key: 'badge-dollar', label: 'Price badge' },
  { key: 'sack', label: 'Money sack' },
  // Security
  { key: 'shield', label: 'Shield' },
  { key: 'shield-check', label: 'Shield check' },
  { key: 'lock', label: 'Lock' },
  { key: 'unlock', label: 'Unlock' },
  { key: 'key', label: 'Key' },
  { key: 'fingerprint', label: 'Fingerprint' },
  { key: 'scan', label: 'Scan' },
  // People
  { key: 'user', label: 'User' },
  { key: 'users', label: 'Users' },
  { key: 'users-group', label: 'User group' },
  { key: 'user-check', label: 'User check' },
  { key: 'id-card', label: 'ID card' },
  { key: 'avatar-circle', label: 'Avatar' },
  // Devices & infra
  { key: 'laptop', label: 'Laptop' },
  { key: 'monitor', label: 'Monitor' },
  { key: 'mobile-phone', label: 'Phone' },
  { key: 'hard-drive', label: 'Hard drive' },
  { key: 'hard-drives', label: 'Storage' },
  { key: 'cloud', label: 'Cloud' },
  { key: 'wifi', label: 'Wi-Fi' },
  { key: 'printer', label: 'Printer' },
  { key: 'keyboard', label: 'Keyboard' },
  { key: 'microchip', label: 'Chip' },
  { key: 'microchip-ai', label: 'AI chip' },
  { key: 'power', label: 'Power' },
  // Code & dev
  { key: 'bracket-curly', label: 'Code' },
  { key: 'terminal', label: 'Terminal' },
  { key: 'code', label: 'Code block' },
  { key: 'bug', label: 'Bug' },
  { key: 'package', label: 'Package' },
  { key: 'database', label: 'Database' },
  { key: 'browser', label: 'Browser' },
  { key: 'puzzle-01', label: 'Plugin' },
  { key: 'coding-branch', label: 'Branch' },
  { key: 'coding-commit', label: 'Commit' },
  { key: 'coding-pull-request', label: 'Pull request' },
  { key: 'robot', label: 'Bot' },
  { key: 'blockchain', label: 'Blockchain' },
  // General & status
  { key: 'layers', label: 'Layers' },
  { key: 'settings-01', label: 'Settings' },
  { key: 'home', label: 'Home' },
  { key: 'eye', label: 'View' },
  { key: 'link-01', label: 'Link' },
  { key: 'download-01', label: 'Download' },
  { key: 'upload-01', label: 'Upload' },
  { key: 'trash', label: 'Delete' },
  { key: 'share', label: 'Share' },
  { key: 'life-buoy', label: 'Support' },
  { key: 'rocket', label: 'Rocket' },
  { key: 'compass', label: 'Compass' },
  { key: 'star', label: 'Star' },
  { key: 'crown', label: 'Crown' },
  { key: 'gift', label: 'Gift' },
  { key: 'ticket', label: 'Ticket' },
  { key: 'tag', label: 'Tag' },
  { key: 'cart', label: 'Cart' },
  { key: 'thumbs-up', label: 'Thumbs up' },
  { key: 'flag-01', label: 'Flag' },
  { key: 'bookmark', label: 'Bookmark' },
  { key: 'pin', label: 'Pin' },
  { key: 'check-circle', label: 'Check' },
  { key: 'check-square', label: 'Checkbox' },
  { key: 'info-circle', label: 'Info' },
  { key: 'info', label: 'Info alt' },
  { key: 'question-circle', label: 'Help' },
  { key: 'alert-triangle', label: 'Warning' },
  { key: 'hash', label: 'Hashtag' },
  { key: 'pencil', label: 'Edit' },
  { key: 'lightning', label: 'Lightning' },
  { key: 'globe-01', label: 'Globe' },
  { key: 'scale-balanced', label: 'Balance' },
  { key: 'certified-01', label: 'Certified' },
]
