// tests/token-exports-emit.test.ts
import { describe, it, expect } from 'vitest'
import { writeFileSync, mkdirSync, rmSync } from 'node:fs'
import { fileURLToPath } from 'node:url'
import { dirname, join } from 'node:path'
import { buildTree, emitJson, emitJs, emitDts } from '../figma-sync/generate-token-exports.mjs'

const toks = [
  { name: 'color-grey-8', value: '#595959', scope: 'dark', section: 'Neutrals' },
  { name: 'bg-layer1', value: '#141414', scope: 'dark', section: 'Surface' },
  { name: 'bg-layer1', value: '#ffffff', scope: 'light', section: 'Surface' },
  { name: 'input-line-border', value: 'var(--color-grey-8)', scope: 'dark', section: 'Neutrals' },
  { name: 'sp-m', value: '16px', scope: 'dark', section: 'Spacing' },
]

const HERE = dirname(fileURLToPath(import.meta.url))
const TMP_DIR = join(HERE, '__tmp-emit-test__')

describe('emit', () => {
  const { dtcg } = buildTree(toks)

  it('emitJson is valid parseable JSON, keeps refs + $extensions', () => {
    const parsed = JSON.parse(emitJson(dtcg))
    expect(parsed.palette['color-grey-8'].$value).toBe('#595959')
    // reference node keeps the {layer.name} form
    expect(parsed.semantic['input-line-border'].$value).toBe('{palette.color-grey-8}')
    // light-overridden node keeps $extensions modes
    expect(parsed.semantic['bg-layer1'].$extensions['tvu.mode']).toEqual({ dark: '#141414', light: '#ffffff' })
  })

  it('emitJs contains resolved literals, no TS-only syntax, and is loadable ESM', async () => {
    const js = emitJs(dtcg)
    expect(js).toContain('export const tokens')
    expect(js).toContain('export const tokensLight')
    // reference resolved to the target's literal value, not left as {...}
    expect(js).toContain("'input-line-border': '#595959'")
    expect(js).not.toContain('{palette.')
    expect(js).not.toContain('as const')
    expect(js).not.toContain('export type')

    mkdirSync(TMP_DIR, { recursive: true })
    const file = join(TMP_DIR, 'tokens.mjs')
    writeFileSync(file, js)
    try {
      const mod = await import(fileURLToPath(new URL(`file://${file}`)))
      expect(mod.tokens.palette['color-grey-8']).toBe('#595959')
      expect(mod.tokens.semantic['input-line-border']).toBe('#595959')
      expect(mod.tokensLight['bg-layer1']).toBe('#ffffff')
    } finally {
      rmSync(TMP_DIR, { recursive: true, force: true })
    }
  })

  it('emitDts exposes declare const tokens/tokensLight + TokenName union', () => {
    const dts = emitDts(dtcg)
    expect(dts).toContain('export declare const tokens')
    expect(dts).toContain('export declare const tokensLight: Record<string, string>')
    expect(dts).toContain('export type TokenName =')
    expect(dts).toContain("'bg-layer1'")
    expect(dts).toContain("readonly 'color-grey-8': '#595959'")
  })
})

// Regression: a light override that is a REFERENCE to another THEMED node
// must resolve to the target's LIGHT value, not its dark value. This is the
// coverage gap that shipped a bug where tokensLight baked in dark values for
// 21 reference light overrides (13 observably wrong). See task-4-report.md.
describe('emitJs light resolution is mode-aware', () => {
  const themedRefToks = [
    { name: 'brand', value: '#2fb54e', scope: 'dark', section: 'Brand' },
    { name: 'brand', value: '#299f45', scope: 'light', section: 'Brand' },
    // chart-color-1 references brand in BOTH scopes
    { name: 'chart-color-1', value: 'var(--brand)', scope: 'dark', section: 'Chart' },
    { name: 'chart-color-1', value: 'var(--brand)', scope: 'light', section: 'Chart' },
  ]
  const { dtcg } = buildTree(themedRefToks)
  const js = emitJs(dtcg)

  it('tokensLight resolves a reference to the TARGET LIGHT value (not dark)', () => {
    // dark tokens side: chart-color-1 → brand DARK
    expect(js).toContain("'chart-color-1': '#2fb54e'")
    // light side: chart-color-1 → brand LIGHT
    expect(js).toContain("'chart-color-1': '#299f45'")
  })

  it('produces loadable ESM with correct dark + light values', async () => {
    mkdirSync(TMP_DIR, { recursive: true })
    const file = join(TMP_DIR, 'tokens-light-ref.mjs')
    writeFileSync(file, js)
    try {
      const mod = await import(fileURLToPath(new URL(`file://${file}`)))
      expect(mod.tokens.palette['chart-color-1']).toBe('#2fb54e') // dark unchanged
      expect(mod.tokensLight['chart-color-1']).toBe('#299f45') // target's LIGHT
    } finally {
      rmSync(TMP_DIR, { recursive: true, force: true })
    }
  })
})
