import test from 'node:test'
import assert from 'node:assert/strict'
import { readFileSync } from 'node:fs'

import {
  cssColorLuminance,
  DEFAULT_DARK_PUBLIC_BRANDING_THEME,
  DEFAULT_PUBLIC_BRANDING,
  derivePublicBrandingThemeTokens,
  emitRootTokensCss,
  isLegacyLightPublicBrandingTheme,
} from '../packages/shared/dist/index.js'

function declarations(block: string) {
  return new Map([...block.matchAll(/--([\w-]+):\s*([^;]+);/g)]
    .map((match) => [`--${match[1]}`, match[2].trim()]))
}

function namedBlock(source: string, name: string) {
  const match = source.match(new RegExp(`${name.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\s*\\{([\\s\\S]*?)\\n\\}`))
  assert.ok(match, `${name} block exists`)
  return match[1]
}

function desktopTokenDeclarations() {
  const globals = readFileSync('apps/desktop/src/renderer/styles/globals.css', 'utf8')
  const generated = readFileSync('apps/desktop/src/renderer/styles/generated/design-tokens.css', 'utf8')
  return {
    generated,
    globals,
    theme: declarations(namedBlock(globals, '@theme inline')),
    root: declarations(namedBlock(generated, ':root')),
  }
}

function expectedThemeTokens() {
  return new Map<string, string>([
    ['--color-base', 'var(--color-base)'],
    ['--color-surface', 'var(--color-surface)'],
    ['--color-surface-hover', 'var(--color-surface-hover)'],
    ['--color-surface-active', 'var(--color-surface-active)'],
    ['--color-elevated', 'var(--color-elevated)'],
    ['--color-border', 'var(--color-border)'],
    ['--color-border-subtle', 'var(--color-border-subtle)'],
    ['--color-border-strong', 'var(--color-border-strong)'],
    ['--color-text', 'var(--color-text)'],
    ['--color-text-secondary', 'var(--color-text-secondary)'],
    ['--color-text-muted', 'var(--color-text-muted)'],
    ['--color-accent', 'var(--color-accent)'],
    ['--color-accent-2', 'var(--color-accent-2)'],
    ['--color-accent-hover', 'var(--color-accent-hover)'],
    ['--color-green', 'var(--color-green)'],
    ['--color-amber', 'var(--color-amber)'],
    ['--color-red', 'var(--color-red)'],
    ['--color-info', 'var(--color-info)'],
    ['--color-accent-foreground', 'var(--color-accent-foreground)'],
  ])
}

function expectedRootTokens() {
  return declarations(namedBlock(emitRootTokensCss(), ':root'))
}

test('shared design tokens generate the desktop root token CSS', () => {
  const desktop = desktopTokenDeclarations()
  const theme = expectedThemeTokens()
  const root = expectedRootTokens()
  const generatedHeader = '/* Generated by scripts/generate-design-token-css.ts from packages/shared/src/design-tokens.ts. Do not edit. */'

  assert.match(desktop.globals, /@import "\.\/generated\/design-tokens\.css";/, 'desktop globals imports generated root tokens')
  assert.doesNotMatch(desktop.globals, /--font-ui:/, 'desktop globals no longer hand-maintains root tokens')
  assert.equal(desktop.generated, `${generatedHeader}\n${emitRootTokensCss()}\n`, 'generated desktop token CSS is emitted from shared tokens')

  for (const [name, value] of theme) {
    assert.equal(desktop.theme.get(name), value, `${name} matches desktop @theme`)
  }
  for (const [name, value] of root) {
    assert.equal(desktop.root.get(name), value, `${name} matches desktop :root`)
  }

  const expectedThemeNames = new Set(theme.keys())
  for (const name of desktop.theme.keys()) {
    assert.ok(expectedThemeNames.has(name), `${name} is represented by shared design tokens`)
  }

  const expectedRootNames = new Set(root.keys())
  for (const name of desktop.root.keys()) {
    assert.ok(expectedRootNames.has(name), `${name} is represented by shared design tokens`)
  }
})

test('shared design tokens emit the canonical density selectors', () => {
  const css = emitRootTokensCss()
  assert.ok(css.includes(':root[data-density="compact"] {\n  --row-pad: 7px;\n  --gap: 13px;\n}'))
  assert.ok(css.includes(':root[data-density="regular"] {\n  --row-pad: 10px;\n  --gap: 18px;\n}'))
  assert.ok(css.includes(':root[data-density="comfy"] {\n  --row-pad: 14px;\n  --gap: 24px;\n}'))
})

test('desktop font package dependencies are present for cloud font serving', () => {
  const packageJson = JSON.parse(readFileSync('apps/desktop/package.json', 'utf8')) as {
    dependencies?: Record<string, string>
  }
  assert.ok(packageJson.dependencies?.['@fontsource-variable/mona-sans'], 'Mona Sans font package is a desktop dependency')
  assert.ok(packageJson.dependencies?.['@fontsource-variable/schibsted-grotesk'], 'Schibsted Grotesk font package is a desktop dependency')
})

test('design docs describe the shared Cloud Web and Desktop token contract', () => {
  const designSystem = readFileSync('docs/design-system.md', 'utf8')
  const designTokens = readFileSync('docs/design-tokens.md', 'utf8')
  const configuration = readFileSync('docs/configuration.md', 'utf8')
  const downstream = readFileSync('docs/downstream.md', 'utf8')
  const downstreamContract = readFileSync('docs/downstream-contract.md', 'utf8')
  const cloudWeb = readFileSync('docs/cloud-web-workbench.md', 'utf8')
  const releaseChecklist = readFileSync('docs/release-checklist.md', 'utf8')

  for (const doc of [designSystem, designTokens, downstream, downstreamContract]) {
    assert.match(doc, /packages\/shared\/src\/design-tokens\.ts/)
  }
  assert.match(designSystem, /emitRootTokensCss\(\)/)
  assert.match(designTokens, /DEFAULT_DARK_BRAND_THEME/)
  assert.match(designTokens, /DEFAULT_LIGHT_BRAND_THEME/)
  assert.match(designTokens, /Studio Semantics/)
  assert.match(designTokens, /Public Branding Theme Keys/)
  assert.match(designTokens, /surfaceHover/)
  assert.match(designTokens, /shadowElevated/)
  assert.match(configuration, /Cloud Web defaults to the shared Desktop Mercury graphite palette/)
  assert.match(configuration, /Legacy light partial theme overrides/)
  assert.match(downstream, /should not fork Cloud Web\s+layout CSS/)
  assert.match(downstreamContract, /bypass the Desktop\/Cloud Web drift gates/)
  assert.match(cloudWeb, /Visual QA Checklist/)
  assert.match(cloudWeb, /\/assets\/fonts\/\*\.woff2/)
  assert.match(releaseChecklist, /Cloud Web and Desktop visual parity checklist/)
})

test('shared public branding default uses the canonical dark theme', () => {
  assert.deepEqual(DEFAULT_PUBLIC_BRANDING.theme, DEFAULT_DARK_PUBLIC_BRANDING_THEME)
})

test('public branding light detection handles accepted literal color tokens', () => {
  assert.ok((cssColorLuminance('#fff') || 0) > 0.95)
  assert.ok((cssColorLuminance('rgb(255, 255, 255)') || 0) > 0.95)
  assert.ok((cssColorLuminance('white') || 0) > 0.95)
  assert.ok((cssColorLuminance('hsl(0, 0%, 100%)') || 0) > 0.95)
  assert.ok((cssColorLuminance('black') ?? 1) < 0.01)
  assert.ok((cssColorLuminance('rgba(255, 255, 255, 0.4)') ?? 1) < 0.55)
  assert.equal(cssColorLuminance('radial-gradient(circle, #fff, #000)'), null)

  assert.equal(isLegacyLightPublicBrandingTheme({ surface: '#fff' }), true)
  assert.equal(isLegacyLightPublicBrandingTheme({ surface: 'rgb(255, 255, 255)' }), true)
  assert.equal(isLegacyLightPublicBrandingTheme({ surface: 'white' }), true)
  assert.equal(isLegacyLightPublicBrandingTheme({ surface: 'hsl(0, 0%, 100%)' }), true)
  assert.equal(derivePublicBrandingThemeTokens({ surface: '#fff' }).text, '#18211c')
})
