import { beforeEach, describe, expect, it } from 'vitest'

import { defaultTheme } from '../../services/theme-engine/presets'
import { _resetCache, getTheme, setThemePartial, teardownTheme } from '../../services/theme-engine/engine'
import { applyAccentFromUrl, getCurrentAccent } from './accent-switcher'
import { ThemeStudio, renderThemeStudio } from './theme-studio'

function resetDom(): void {
  document.head.innerHTML = ''
  document.body.innerHTML = ''
  document.documentElement.removeAttribute('data-theme')
  document.documentElement.removeAttribute('data-accent')
  document.documentElement.removeAttribute('data-density')
  document.documentElement.removeAttribute('data-icon-set')
  document.documentElement.removeAttribute('style')
  window.history.replaceState({}, '', '/')
}

describe('ThemeStudio', () => {
  beforeEach(() => {
    localStorage.clear()
    teardownTheme()
    _resetCache()
    resetDom()
  })

  it('renders and wires presets, switchers, sliders, and advanced icon overrides', () => {
    const studio = new ThemeStudio()
    document.body.appendChild(studio.el)

    expect(studio.el.textContent).toContain('Appearance')
    expect(studio.el.querySelectorAll('.theme-studio-preset')).toHaveLength(6)
    expect(studio.el.querySelector('.theme-studio-preview-tile')).toBeTruthy()

    const paperPreset = studio.el.querySelector('[data-preset-id="paper-light"]') as HTMLButtonElement
    paperPreset.click()
    expect(getTheme().mode).toBe('light')

    const preview = studio.el.querySelector('.theme-studio-preview-tile') as HTMLElement
    expect(preview.dataset.mode).toBe('light')

    const glassButton = studio.el.querySelector('[data-theme="glass"]') as HTMLButtonElement
    glassButton.click()
    expect(getTheme().mode).toBe('glass')

    const accentButton = studio.el.querySelector('[data-accent="violet"]') as HTMLButtonElement
    accentButton.click()
    expect(getCurrentAccent()).toBe('violet')

    const densityButton = studio.el.querySelector('[data-density="compact"]') as HTMLButtonElement
    densityButton.click()
    expect(getTheme().density).toBe('compact')

    const fontTile = studio.el.querySelector('[data-font="roboto"]') as HTMLButtonElement
    fontTile.dispatchEvent(new FocusEvent('focus'))
    fontTile.click()
    expect(getTheme().font).toBe('roboto')
    expect(document.head.querySelector('link[id^="cm-gfont-"]')).toBeTruthy()

    const iconTile = studio.el.querySelector('[data-icon-set="countermeasure"]') as HTMLButtonElement
    expect(iconTile.textContent).toContain('Brand')
    iconTile.click()
    expect(getTheme().iconSet).toBe('countermeasure')

    const glassSlider = studio.el.querySelector('.preview-glass-slider__input') as HTMLInputElement
    glassSlider.value = '0.12'
    glassSlider.dispatchEvent(new Event('input', { bubbles: true }))
    expect(getTheme().transparency).toBe(0.12)

    const radiusSlider = studio.el.querySelector('.preview-radius-slider__input') as HTMLInputElement
    radiusSlider.value = '15'
    radiusSlider.dispatchEvent(new Event('input', { bubbles: true }))
    expect(getTheme().radius).toBe(15)

    const details = studio.el.querySelector('details') as HTMLDetailsElement
    details.open = true
    details.dispatchEvent(new Event('toggle'))
    expect(details.textContent).toContain('Hide')

    const change = studio.el.querySelector('.theme-studio-icon-matrix__change') as HTMLButtonElement
    const reset = studio.el.querySelector('.theme-studio-icon-matrix__reset') as HTMLButtonElement
    change.click()
    expect(Object.keys(getTheme().iconOverrides).length).toBeGreaterThan(0)
    reset.click()
    expect(Object.keys(getTheme().iconOverrides)).toHaveLength(0)

    setThemePartial({ accent: 'rose' })
    const resetButton = Array.from(studio.el.querySelectorAll('button')).find(
      button => button.textContent === 'Reset to default'
    ) as HTMLButtonElement
    resetButton.click()
    expect(getTheme()).toEqual(defaultTheme())
  })

  it('renders into a container and replaces existing content', () => {
    const container = document.createElement('div')
    container.innerHTML = '<p>stale</p>'

    const studio = renderThemeStudio(container, { showTabs: false, showHeader: false, showBrandSection: false })

    expect(studio.el.parentElement).toBe(container)
    expect(container.textContent).not.toContain('stale')
    expect(container.textContent).not.toContain('Appearance')
    expect(container.querySelector('.theme-studio-brand-note')).toBeNull()
  })

  it('applies a valid accent from the URL', () => {
    window.history.replaceState({}, '', '/?accent=rose')

    applyAccentFromUrl()

    expect(getCurrentAccent()).toBe('rose')
  })
})
