/**
 * StatCard - Metric display card with trend indicator
 * @countermeasure/web-components/display/stat-card
 */

import { type StatCardConfig, type TrendConfig, type TrendDirection } from './types'
import { resolveContainer, uniqueId } from '../../primitives/utils'
import { setSafeIconHtml } from '../../utils/sanitize'

export type { StatCardConfig, TrendConfig, TrendDirection } from './types'

/** SVG arrow icons for trend directions */
const TREND_ARROWS: Record<TrendDirection, string> = {
  up: '<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="m18 15-6-6-6 6"/></svg>',
  down: '<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="m6 9 6 6 6-6"/></svg>',
  neutral:
    '<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="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>',
}

export class StatCard {
  public readonly el: HTMLDivElement

  private readonly statCardId: string
  private labelEl: HTMLSpanElement
  private valueEl: HTMLDivElement
  private trendEl: HTMLDivElement | null = null
  private iconEl: HTMLDivElement | null = null

  constructor(config: StatCardConfig) {
    this.statCardId = uniqueId('cmm-stat-card')

    // Create root element
    this.el = document.createElement('div')
    this.el.id = this.statCardId
    this.el.className = this.buildClassName(config.className)

    // Create header (label + icon)
    const headerEl = document.createElement('div')
    headerEl.className = 'cmm-stat-card__header'

    this.labelEl = document.createElement('span')
    this.labelEl.className = 'cmm-stat-card__label'
    this.labelEl.textContent = config.label
    headerEl.appendChild(this.labelEl)

    if (config.icon !== undefined) {
      this.iconEl = document.createElement('div')
      this.iconEl.className = 'cmm-stat-card__icon'
      this.iconEl.setAttribute('aria-hidden', 'true')
      setSafeIconHtml(this.iconEl, config.icon)
      headerEl.appendChild(this.iconEl)
    }

    this.el.appendChild(headerEl)

    // Create value
    this.valueEl = document.createElement('div')
    this.valueEl.className = 'cmm-stat-card__value'
    this.valueEl.textContent = this.formatValue(config.value)
    this.el.appendChild(this.valueEl)

    // Create trend
    if (config.trend !== undefined) {
      this.trendEl = this.createTrendEl(config.trend)
      this.el.appendChild(this.trendEl)
    }

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

  /** Update the displayed value */
  setValue(value: string | number): void {
    this.valueEl.textContent = this.formatValue(value)
  }

  /** Update or set the trend indicator */
  setTrend(trend: TrendConfig): void {
    if (this.trendEl !== null) {
      this.trendEl.remove()
    }
    this.trendEl = this.createTrendEl(trend)
    this.el.appendChild(this.trendEl)
  }

  /** Update the label text */
  setLabel(label: string): void {
    this.labelEl.textContent = label
  }

  /** Remove the stat card from the DOM and clean up */
  destroy(): void {
    this.el.remove()
  }

  private buildClassName(extra?: string): string {
    const classes = ['cmm-stat-card']
    if (extra) {
      classes.push(extra)
    }
    return classes.join(' ')
  }

  private formatValue(value: string | number): string {
    if (typeof value === 'number') {
      return String(value)
    }
    return value
  }

  private createTrendEl(trend: TrendConfig): HTMLDivElement {
    const trendEl = document.createElement('div')
    trendEl.className = `cmm-stat-card__trend cmm-stat-card__trend--${trend.direction}`

    // Arrow icon
    const arrowEl = document.createElement('span')
    arrowEl.className = 'cmm-stat-card__trend-arrow'
    arrowEl.setAttribute('aria-hidden', 'true')
    arrowEl.innerHTML = TREND_ARROWS[trend.direction]
    trendEl.appendChild(arrowEl)

    // Trend value
    const valueSpan = document.createElement('span')
    valueSpan.className = 'cmm-stat-card__trend-value'
    valueSpan.textContent = trend.value
    trendEl.appendChild(valueSpan)

    // Trend label
    if (trend.label !== undefined) {
      const labelSpan = document.createElement('span')
      labelSpan.className = 'cmm-stat-card__trend-label'
      labelSpan.textContent = trend.label
      trendEl.appendChild(labelSpan)
    }

    return trendEl
  }
}
