/**
 * Alert - Dismissible alert/notification box
 * @countermeasure/web-components/display/alert
 */

import { type AlertConfig, type AlertVariant } from './types'
import { resolveContainer, uniqueId } from '../../primitives/utils'
import { setSafeIconHtml } from '../../utils/sanitize'

export type { AlertConfig, AlertVariant } from './types'

/** Default SVG icons per alert variant */
const VARIANT_ICONS: Record<AlertVariant, string> = {
  info: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/></svg>',
  success:
    '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="m9 12 2 2 4-4"/></svg>',
  warning:
    '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3Z"/><path d="M12 9v4"/><path d="M12 17h.01"/></svg>',
  error:
    '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="m15 9-6 6"/><path d="m9 9 6 6"/></svg>',
}

export class Alert {
  public readonly el: HTMLDivElement

  private readonly alertId: string
  private descriptionEl: HTMLDivElement
  private dismissBtn: HTMLButtonElement | null = null
  private readonly dismissHandler: (() => void) | undefined
  private readonly dismissBtnClickHandler: (() => void) | null = null
  private readonly transitionEndHandler: (() => void) | null = null

  constructor(config: AlertConfig) {
    this.alertId = uniqueId('cmm-alert')
    this.dismissHandler = config.onDismiss

    const variant = config.variant ?? 'info'

    // Create root element
    this.el = document.createElement('div')
    this.el.id = this.alertId
    this.el.className = this.buildClassName(variant, config.className)
    this.el.setAttribute('role', 'alert')

    // Create icon
    const iconEl = document.createElement('div')
    iconEl.className = 'cmm-alert__icon'
    iconEl.setAttribute('aria-hidden', 'true')
    setSafeIconHtml(iconEl, config.icon ?? VARIANT_ICONS[variant])
    this.el.appendChild(iconEl)

    // Create content container
    const contentEl = document.createElement('div')
    contentEl.className = 'cmm-alert__content'

    // Create title if provided
    if (config.title !== undefined) {
      const titleEl = document.createElement('div')
      titleEl.className = 'cmm-alert__title'
      titleEl.textContent = config.title
      contentEl.appendChild(titleEl)
    }

    // Create description
    this.descriptionEl = document.createElement('div')
    this.descriptionEl.className = 'cmm-alert__description'
    this.descriptionEl.textContent = config.description
    contentEl.appendChild(this.descriptionEl)

    this.el.appendChild(contentEl)

    // Create dismiss button
    if (config.dismissible === true) {
      this.dismissBtn = document.createElement('button')
      this.dismissBtn.className = 'cmm-alert__dismiss'
      this.dismissBtn.setAttribute('aria-label', 'Dismiss')
      this.dismissBtn.type = 'button'
      this.dismissBtn.textContent = '\u00d7'

      const clickHandler = () => {
        this.dismiss()
      }
      this.dismissBtnClickHandler = clickHandler
      this.dismissBtn.addEventListener('click', clickHandler)
      this.el.appendChild(this.dismissBtn)
    }

    // Set up transition end handler for removal after fade out
    const transitionHandler = () => {
      if (this.el.classList.contains('cmm-alert--dismissed')) {
        this.el.remove()
      }
    }
    this.transitionEndHandler = transitionHandler
    this.el.addEventListener('transitionend', transitionHandler)

    // Mount if container provided
    if (config.container !== undefined) {
      const parent = resolveContainer(config.container)
      parent.appendChild(this.el)
    }
  }

  /** Update the alert description text */
  setDescription(text: string): void {
    this.descriptionEl.textContent = text
  }

  /** Dismiss the alert with a fade-out animation */
  dismiss(): void {
    this.el.classList.add('cmm-alert--dismissed')
    if (this.dismissHandler !== undefined) {
      this.dismissHandler()
    }
  }

  /** Remove the alert from the DOM and clean up */
  destroy(): void {
    if (this.dismissBtn !== null && this.dismissBtnClickHandler !== null) {
      this.dismissBtn.removeEventListener('click', this.dismissBtnClickHandler)
    }
    if (this.transitionEndHandler !== null) {
      this.el.removeEventListener('transitionend', this.transitionEndHandler)
    }
    this.el.remove()
  }

  private buildClassName(variant: AlertVariant, extra?: string): string {
    const classes = ['cmm-alert', `cmm-alert--${variant}`]
    if (extra) {
      classes.push(extra)
    }
    return classes.join(' ')
  }
}
