// @vitest-environment happy-dom
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { cleanup, render, waitFor } from '@testing-library/react'
import { accentTokensToCssVars, generateAdminThemeTokens } from '@actuate-media/cms-core/appearance'

import { ThemeProvider } from '../../components/ThemeProvider.js'
import { ADMIN_ROOT_ATTR, getAdminRootElement } from '../../lib/admin-root-element.js'

/**
 * Regression: accent overrides must land on the inner AdminRoot shell, not a
 * consumer wrapper `.actuate-admin` that also defines static --acc tokens.
 */
afterEach(cleanup)

const storage = new Map<string, string>()

beforeEach(() => {
  storage.clear()
  vi.stubGlobal('localStorage', {
    getItem: (key: string) => storage.get(key) ?? null,
    setItem: (key: string, value: string) => storage.set(key, value),
    removeItem: (key: string) => storage.delete(key),
    clear: () => storage.clear(),
  })
})

function mountNestedAdminShell() {
  const outer = document.createElement('div')
  outer.className = 'actuate-admin'
  document.body.appendChild(outer)

  const inner = document.createElement('div')
  inner.className = 'actuate-admin'
  inner.setAttribute(ADMIN_ROOT_ATTR, '')
  outer.appendChild(inner)

  return { outer, inner }
}

describe('getAdminRootElement', () => {
  afterEach(() => {
    document.body.innerHTML = ''
  })

  it('prefers the marked admin shell over an outer wrapper', () => {
    const { outer, inner } = mountNestedAdminShell()
    expect(getAdminRootElement()).toBe(inner)
    expect(getAdminRootElement()).not.toBe(outer)
  })

  it('falls back to .actuate-admin when no marked root exists', () => {
    const root = document.createElement('div')
    root.className = 'actuate-admin'
    document.body.appendChild(root)
    expect(getAdminRootElement()).toBe(root)
  })
})

describe('ThemeProvider accent application', () => {
  afterEach(() => {
    document.body.innerHTML = ''
  })

  it('applies accent tokens to the marked inner admin root when nested', async () => {
    const { outer, inner } = mountNestedAdminShell()

    render(
      <ThemeProvider>
        <span>child</span>
      </ThemeProvider>,
      { container: inner },
    )

    const expected = accentTokensToCssVars(
      generateAdminThemeTokens({ adminAccentColor: 'purple' }, 'light'),
    )

    await waitFor(() => {
      expect(inner.style.getPropertyValue('--acc')).toBe(expected['--acc']!)
    })
    expect(inner.style.getPropertyValue('--primary')).toBe(expected['--primary']!)
    expect(outer.style.getPropertyValue('--acc')).toBe('')
  })
})
