/**
 * CounterMeasure brand helpers and vanilla components
 * @countermeasure/web-components/components/brand
 */

import {
  type BrandSize,
  type ConnectorLogoConfig,
  type ConnectorLogoSize,
  type DiamondConfig,
  type WordmarkConfig,
} from './types'
import { resolveContainer, uniqueId } from '../../primitives/utils'

export type {
  BrandSize,
  ConnectorLogoConfig,
  ConnectorLogoSize,
  DiamondConfig,
  WordmarkConfig,
  WordmarkVariant,
} from './types'

const SVG_NS = 'http://www.w3.org/2000/svg'
const WORDMARK_ASPECT_RATIO = 220 / 32

export const CONNECTOR_LOGO_PALETTE = {
  Splunk: '#FF6B35',
  Sentinel: '#0078D4',
  Elastic: '#00BFB3',
  CrowdStrike: '#FA0F00',
  Defender: '#0078D4',
  SentinelOne: '#6300E5',
  MISP: '#00897B',
  OpenCTI: '#5C6BC0',
  'MITRE ATT&CK': '#C8102E',
  'Palo Alto': '#FA582D',
  'Carbon Black': '#000000',
  default: '#475569',
} as const

const CONNECTOR_LOGO_TONES: Record<keyof typeof CONNECTOR_LOGO_PALETTE, string> = {
  Splunk: 'splunk',
  Sentinel: 'sentinel',
  Elastic: 'elastic',
  CrowdStrike: 'crowdstrike',
  Defender: 'defender',
  SentinelOne: 'sentinelone',
  MISP: 'misp',
  OpenCTI: 'opencti',
  'MITRE ATT&CK': 'mitre-attack',
  'Palo Alto': 'palo-alto',
  'Carbon Black': 'carbon-black',
  default: 'default',
}

const BRAND_SIZE_CLASS_VALUES = new Set<number>([16, 20, 24, 32, 48, 64])

export class Diamond {
  public readonly el: SVGSVGElement

  constructor(config: DiamondConfig = {}) {
    this.el = createDiamondSvg(config)

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

  destroy(): void {
    this.el.remove()
  }
}

export class Wordmark {
  public readonly el: HTMLDivElement
  public readonly svg: SVGSVGElement
  private subtitleEl: HTMLSpanElement | null = null

  constructor(config: WordmarkConfig = {}) {
    this.el = document.createElement('div')
    this.el.id = uniqueId('cmm-wordmark')
    this.el.className = buildWordmarkClassName(config)
    this.applyAccessibility(config)

    this.svg = createWordmarkSvg(config)
    this.svg.setAttribute('aria-hidden', 'true')
    this.el.appendChild(this.svg)

    if (config.subtitle !== undefined) {
      this.subtitleEl = document.createElement('span')
      this.subtitleEl.className = 'cmm-wordmark__subtitle'
      this.subtitleEl.textContent = config.subtitle
      this.el.appendChild(this.subtitleEl)
    }

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

  setSubtitle(subtitle: string | null): void {
    if (subtitle === null) {
      this.subtitleEl?.remove()
      this.subtitleEl = null
      return
    }

    if (this.subtitleEl === null) {
      this.subtitleEl = document.createElement('span')
      this.subtitleEl.className = 'cmm-wordmark__subtitle'
      this.el.appendChild(this.subtitleEl)
    }

    this.subtitleEl.textContent = subtitle
  }

  destroy(): void {
    this.el.remove()
  }

  private applyAccessibility(config: WordmarkConfig): void {
    if (config.decorative === true) {
      this.el.setAttribute('aria-hidden', 'true')
      return
    }

    this.el.setAttribute('role', 'img')
    this.el.setAttribute('aria-label', config.label ?? 'CounterMeasure')
  }
}

export class ConnectorLogo {
  public readonly el: HTMLSpanElement

  constructor(config: ConnectorLogoConfig) {
    this.el = document.createElement('span')
    this.el.id = uniqueId('cmm-connector-logo')
    this.el.className = buildConnectorLogoClassName(config)
    this.applyAccessibility(config)

    if (config.src !== undefined) {
      const imageEl = document.createElement('img')
      imageEl.className = 'cmm-connector-logo__asset'
      imageEl.src = config.src
      imageEl.alt = ''
      imageEl.setAttribute('aria-hidden', 'true')
      this.el.appendChild(imageEl)
    } else if (config.svg !== undefined) {
      const assetEl = document.createElement('span')
      assetEl.className = 'cmm-connector-logo__asset'
      assetEl.setAttribute('aria-hidden', 'true')
      assetEl.appendChild(config.svg)
      this.el.appendChild(assetEl)
    } else {
      this.el.textContent = getConnectorLogoInitial(config.name)
    }

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

  destroy(): void {
    this.el.remove()
  }

  private applyAccessibility(config: ConnectorLogoConfig): void {
    if (config.decorative === true) {
      this.el.setAttribute('aria-hidden', 'true')
      return
    }

    this.el.setAttribute('role', 'img')
    this.el.setAttribute('aria-label', config.label ?? `${config.name} connector`)
  }
}

export function createDiamondSvg(config: DiamondConfig = {}): SVGSVGElement {
  const size = config.size ?? 24
  const svg = createSvgRoot('0 0 46.64 46.64', size, size)
  svg.id = uniqueId('cmm-diamond')
  svg.classList.add('cmm-diamond')

  const sizeClass = getBrandSizeClass('cmm-diamond', size)
  if (sizeClass !== null) {
    svg.classList.add(sizeClass)
  }

  if (config.className) {
    svg.classList.add(...splitClassName(config.className))
  }

  if (config.decorative === false) {
    svg.setAttribute('role', 'img')
    svg.setAttribute('aria-label', config.label ?? 'CounterMeasure diamond')
  } else {
    svg.setAttribute('aria-hidden', 'true')
  }

  appendDiamondRects(svg, 'cmm-diamond__foreground')
  return svg
}

export function createWordmarkSvg(config: WordmarkConfig = {}): SVGSVGElement {
  const height = config.size ?? 32
  const width = Math.round(height * WORDMARK_ASPECT_RATIO * 100) / 100
  const svg = createSvgRoot('0 0 220 32', width, height)
  svg.classList.add('cmm-wordmark__svg')

  const markGroup = document.createElementNS(SVG_NS, 'g')
  markGroup.setAttribute('transform', 'translate(0,3)')
  appendWordmarkDiamondRects(markGroup)
  svg.appendChild(markGroup)

  const textEl = document.createElementNS(SVG_NS, 'text')
  textEl.setAttribute('x', '42')
  textEl.setAttribute('y', '22')
  textEl.setAttribute('class', 'cmm-wordmark__text')
  textEl.setAttribute('font-family', 'Outfit, sans-serif')
  textEl.setAttribute('font-size', '18')
  textEl.setAttribute('font-weight', '600')
  textEl.setAttribute('letter-spacing', '-0.01em')
  textEl.textContent = 'CounterMeasure'
  svg.appendChild(textEl)

  return svg
}

export function getConnectorLogoColor(name: string): string {
  const paletteKey = getConnectorPaletteKey(name)
  return CONNECTOR_LOGO_PALETTE[paletteKey]
}

export function getConnectorLogoTone(name: string): string {
  const paletteKey = getConnectorPaletteKey(name)
  return CONNECTOR_LOGO_TONES[paletteKey]
}

export function getConnectorLogoInitial(name: string): string {
  const match = name.trim().match(/[A-Za-z0-9]/)
  return match?.[0]?.toUpperCase() ?? 'C'
}

export function getBrandSizeClass(prefix: string, size: BrandSize | number): string | null {
  if (BRAND_SIZE_CLASS_VALUES.has(size)) {
    return `${prefix}--${String(size)}`
  }

  return null
}

export function getConnectorLogoSizeClass(size: ConnectorLogoSize = 32): string {
  return `cmm-connector-logo--${String(size)}`
}

function buildWordmarkClassName(config: WordmarkConfig): string {
  const variant = config.variant ?? 'auto'
  const classes = ['cmm-wordmark', `cmm-wordmark--${variant}`]

  if (config.className) {
    classes.push(config.className)
  }

  return classes.join(' ')
}

function buildConnectorLogoClassName(config: ConnectorLogoConfig): string {
  const classes = [
    'cmm-connector-logo',
    getConnectorLogoSizeClass(config.size),
    `cmm-connector-logo--vendor-${getConnectorLogoTone(config.name)}`,
  ]

  if (config.src !== undefined || config.svg !== undefined) {
    classes.push('cmm-connector-logo--asset')
  }

  if (config.className) {
    classes.push(config.className)
  }

  return classes.join(' ')
}

function getConnectorPaletteKey(name: string): keyof typeof CONNECTOR_LOGO_PALETTE {
  const normalizedName = name.trim().toLowerCase()

  for (const key of Object.keys(CONNECTOR_LOGO_PALETTE) as Array<
    keyof typeof CONNECTOR_LOGO_PALETTE
  >) {
    if (key.toLowerCase() === normalizedName) {
      return key
    }
  }

  return 'default'
}

function createSvgRoot(
  viewBox: string,
  width: BrandSize | number,
  height: BrandSize | number
): SVGSVGElement {
  const svg = document.createElementNS(SVG_NS, 'svg')
  svg.setAttribute('xmlns', SVG_NS)
  svg.setAttribute('viewBox', viewBox)
  svg.setAttribute('width', String(width))
  svg.setAttribute('height', String(height))
  return svg
}

function appendDiamondRects(svg: SVGSVGElement, foregroundClassName: string): void {
  svg.appendChild(
    createRect('2.62', '16.42', '13.8', '13.8', '0.57', '-13.7 13.56', foregroundClassName)
  )
  svg.appendChild(
    createRect('16.42', '30.22', '13.8', '13.8', '0.57', '-19.42 27.36', 'cmm-diamond__slate')
  )
  svg.appendChild(
    createRect('16.42', '2.62', '13.8', '13.8', '0.57', '0.1 19.28', 'cmm-diamond__orange')
  )
}

function appendWordmarkDiamondRects(group: SVGGElement): void {
  group.appendChild(
    createRect('1.78', '11.16', '9.4', '9.4', '0.4', '-9.32 9.22', 'cmm-wordmark__foreground')
  )
  group.appendChild(
    createRect('11.16', '20.54', '9.4', '9.4', '0.4', '-13.21 18.6', 'cmm-wordmark__slate')
  )
  group.appendChild(
    createRect('11.16', '1.78', '9.4', '9.4', '0.4', '0.07 13.11', 'cmm-wordmark__orange')
  )
}

function createRect(
  x: string,
  y: string,
  width: string,
  height: string,
  rx: string,
  transformTranslate: string,
  className: string
): SVGRectElement {
  const rect = document.createElementNS(SVG_NS, 'rect')
  rect.setAttribute('x', x)
  rect.setAttribute('y', y)
  rect.setAttribute('width', width)
  rect.setAttribute('height', height)
  rect.setAttribute('rx', rx)
  rect.setAttribute('transform', `translate(${transformTranslate}) rotate(-45)`)
  rect.setAttribute('class', className)
  return rect
}

function splitClassName(className: string): string[] {
  return className.split(/\s+/).filter(Boolean)
}
