/**
 * App Switcher Module
 *
 * Shared app switcher functionality for CounterMeasure applications.
 * Displays a dropdown menu for switching between different apps.
 *
 * Usage:
 * - Add data-app-switcher to the container element
 * - Add data-app-switcher-grid for the menu grid
 * - Add data-app-switcher-current for the current app name display
 * - Add data-app-switcher-icon for the trigger icon container
 * - Configure apps via getWebConfig() or pass directly
 */

import { escapeHtml, setSafeIconHtml } from '../utils/sanitize'

export interface AppLink {
  id: string
  name: string
  href: string
  description?: string
  status?: 'active' | 'preview' | 'coming_soon'
  icon?: string
}

export interface AppSwitcherConfig {
  apps?: AppLink[]
  getApps?: () => AppLink[]
}

// Track currently open instance globally
let currentOpenInstance: HTMLElement | null = null

/**
 * Default logo SVG — CounterMeasure plain logo (3 diamonds).
 * Uses cm-logo__diamond--* classes for light/dark theme support.
 */
const DEFAULT_LOGO_ICON = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 66.55 94.52" width="24" height="34"><rect class="cm-logo__diamond--primary" x="5.31" y="33.28" width="27.97" height="27.97" rx="1.17" transform="translate(-27.77 27.48) rotate(-45)"/><rect class="cm-logo__diamond--muted" x="33.28" y="61.24" width="27.97" height="27.97" rx="1.17" transform="translate(-39.35 55.45) rotate(-45)"/><rect class="cm-logo__diamond--accent" x="33.28" y="5.31" width="27.97" height="27.97" rx="1.17" transform="translate(0.2 39.07) rotate(-45)"/></svg>`

function renderIconMarkup(icon: string, size: number): string {
  if (icon.trimStart().startsWith('<')) {
    return icon
  }
  return `<svg xmlns="http://www.w3.org/2000/svg" width="${String(size)}" height="${String(size)}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="${escapeHtml(icon)}"/></svg>`
}

/**
 * Update the trigger icon to show the active app's icon or the default logo.
 */
function updateTriggerIcon(iconContainer: HTMLElement | null, activeApp: AppLink | null): void {
  if (!iconContainer) {
    return
  }

  const iconPath = activeApp?.icon
  if (typeof iconPath === 'string' && iconPath.length > 0) {
    setSafeIconHtml(iconContainer, renderIconMarkup(iconPath, 20))
    iconContainer.classList.remove('app-switcher__logo-mark')
  } else {
    setSafeIconHtml(iconContainer, DEFAULT_LOGO_ICON)
    iconContainer.classList.add('app-switcher__logo-mark')
  }
}

/**
 * Open an app-switcher instance.
 */
function openAppSwitcher(
  container: HTMLElement,
  trigger: HTMLButtonElement,
  panel: HTMLElement
): void {
  container.classList.add('app-switcher--open')
  trigger.setAttribute('aria-expanded', 'true')
  currentOpenInstance = container

  // Focus first non-disabled item
  const firstItem = panel.querySelector<HTMLElement>(
    '.app-switcher__item:not(.app-switcher__item--disabled)'
  )
  firstItem?.focus()
}

/**
 * Close an app-switcher instance.
 */
function closeAppSwitcher(container: HTMLElement): void {
  const trigger = container.querySelector<HTMLButtonElement>('.app-switcher__trigger')

  container.classList.remove('app-switcher--open')
  trigger?.setAttribute('aria-expanded', 'false')
  trigger?.focus()

  if (currentOpenInstance === container) {
    currentOpenInstance = null
  }
}

/**
 * Toggle app-switcher open/closed state.
 */
function toggleAppSwitcher(
  container: HTMLElement,
  trigger: HTMLButtonElement,
  panel: HTMLElement
): void {
  const isOpen = container.classList.contains('app-switcher--open')

  if (isOpen) {
    closeAppSwitcher(container)
  } else {
    // Close any other open instance first
    if (currentOpenInstance && currentOpenInstance !== container) {
      closeAppSwitcher(currentOpenInstance)
    }
    openAppSwitcher(container, trigger, panel)
  }
}

/**
 * Initialize a single app-switcher instance.
 */
function initSingleAppSwitcher(
  container: HTMLElement,
  apps: AppLink[],
  activeApp: AppLink | null,
  path: string
): void {
  const grid = container.querySelector<HTMLElement>('[data-app-switcher-grid]')
  const current = container.querySelector<HTMLElement>('[data-app-switcher-current]')
  const iconContainer = container.querySelector<HTMLElement>('[data-app-switcher-icon]')
  const trigger = container.querySelector<HTMLButtonElement>('.app-switcher__trigger')
  const panel = container.querySelector<HTMLElement>('.app-switcher__panel')

  if (!grid || !trigger || !panel) {
    return
  }

  // Show container and reset state
  container.hidden = false
  container.classList.remove('app-switcher--single', 'app-switcher--empty')
  grid.innerHTML = ''

  // Update trigger icon and title based on active app
  const activeName = activeApp?.name ?? 'Apps'
  updateTriggerIcon(iconContainer, activeApp)
  trigger.setAttribute('title', activeName)

  // Handle empty state
  if (apps.length === 0) {
    container.classList.add('app-switcher--empty')
    if (current) {
      current.textContent = activeName
    }
    return
  }

  // Handle single app state
  if (apps.length === 1) {
    container.classList.add('app-switcher--single')
    if (current && apps[0]) {
      current.textContent = apps[0].name
    }
    return
  }

  // Create backdrop element for this instance
  const backdrop = document.createElement('div')
  backdrop.className = 'app-switcher__backdrop'
  container.appendChild(backdrop)

  // Click handler on trigger
  trigger.addEventListener('click', e => {
    e.preventDefault()
    e.stopPropagation()
    toggleAppSwitcher(container, trigger, panel)
  })

  // Close on backdrop click
  backdrop.addEventListener('click', () => {
    closeAppSwitcher(container)
  })

  // Close on menu item click (for navigation)
  panel.addEventListener('click', e => {
    const target = e.target as HTMLElement
    if (target.closest('.app-switcher__item:not(.app-switcher__item--disabled)')) {
      closeAppSwitcher(container)
    }
  })

  // Build menu items
  apps.forEach(app => {
    const status = app.status ?? 'active'
    const isDisabled = status === 'coming_soon'
    const isActive = path.startsWith(app.href)

    const item = document.createElement(isDisabled ? 'div' : 'a')
    item.className = 'app-switcher__item'
    item.setAttribute('role', 'menuitem')
    item.setAttribute('title', app.name)

    if (isActive) {
      item.classList.add('app-switcher__item--active')
    }
    if (isDisabled) {
      item.classList.add('app-switcher__item--disabled')
      item.setAttribute('aria-disabled', 'true')
    } else {
      ;(item as HTMLAnchorElement).href = app.href
    }

    // Add icon if available
    if (typeof app.icon === 'string' && app.icon.length > 0) {
      const iconWrapper = document.createElement('span')
      iconWrapper.className = 'app-switcher__icon'
      iconWrapper.setAttribute('aria-hidden', 'true')
      setSafeIconHtml(iconWrapper, renderIconMarkup(app.icon, 18))
      item.appendChild(iconWrapper)
    }

    // Content wrapper for text (title + description)
    const content = document.createElement('span')
    content.className = 'app-switcher__content'

    const title = document.createElement('span')
    title.className = 'app-switcher__title'
    title.textContent = app.name
    content.appendChild(title)

    if (typeof app.description === 'string' && app.description.length > 0) {
      const desc = document.createElement('span')
      desc.className = 'app-switcher__desc'
      desc.textContent = app.description
      content.appendChild(desc)
    }

    item.appendChild(content)

    if (status !== 'active') {
      const badge = document.createElement('span')
      badge.className = 'app-switcher__badge'
      badge.textContent = status === 'preview' ? 'Preview' : 'Coming soon'
      item.appendChild(badge)
    }

    grid.appendChild(item)
  })

  // Set current app name
  if (current) {
    current.textContent = activeName
  }
}

/**
 * Initialize all app-switcher instances on the page.
 */
export function initAppSwitcher(config?: AppSwitcherConfig): void {
  const containers = document.querySelectorAll<HTMLElement>('[data-app-switcher]')
  if (containers.length === 0) {
    return
  }

  // Get apps from config or try to find web config in DOM
  let apps: AppLink[] = []
  if (config?.apps) {
    apps = config.apps
  } else if (config?.getApps) {
    apps = config.getApps()
  } else {
    // Try to get from web-config element in DOM
    const configEl = document.getElementById('web-config')
    const content = configEl?.textContent
    if (typeof content === 'string' && content.length > 0) {
      try {
        const parsed = JSON.parse(content) as { apps?: AppLink[] }
        apps = parsed.apps ?? []
      } catch {
        // Ignore parse errors
      }
    }
  }

  const path = window.location.pathname

  // Determine active app
  let activeApp: AppLink | null = null
  for (const app of apps) {
    if (path.startsWith(app.href)) {
      activeApp = app
      break
    }
  }

  // Initialize each app-switcher instance
  containers.forEach(container => {
    initSingleAppSwitcher(container, apps, activeApp, path)
  })

  // Global escape key handler (single listener for all instances)
  document.addEventListener('keydown', e => {
    if (e.key === 'Escape' && currentOpenInstance) {
      closeAppSwitcher(currentOpenInstance)
    }
  })
}

/**
 * Get the currently open app switcher instance.
 */
export function getCurrentOpenInstance(): HTMLElement | null {
  return currentOpenInstance
}

/**
 * Close any open app switcher.
 */
export function closeAnyOpenAppSwitcher(): void {
  if (currentOpenInstance) {
    closeAppSwitcher(currentOpenInstance)
  }
}
