import { describe, it, expect } from 'vitest'
import { readFileSync, existsSync, readdirSync } from 'node:fs'
import { resolve, dirname } from 'node:path'
import { fileURLToPath } from 'node:url'
import { checkReactDemo, checkVueDemo, deriveInScope } from '../scripts/audit-demo-slot-boolean-coverage.mjs'

const __dirname = dirname(fileURLToPath(import.meta.url))

const POPUPBOX = { name: 'PopupBox', canonicalImport: 'PopupBox', hasDefaultSlot: true, namedSlots: ['footer'], hasSlot: true, boolProps: ['closable', 'showFooter'] }
const NOTIF = { name: 'Notification', canonicalImport: 'Notification', hasDefaultSlot: false, namedSlots: [], hasSlot: false, boolProps: ['closable'] }
const BUTTON = { name: 'Button', canonicalImport: 'ButtonBridge', hasDefaultSlot: true, namedSlots: [], hasSlot: true, boolProps: [] }

describe('deriveInScope', () => {
  it('includes slot-only and boolean-only, excludes neither', () => {
    const cfgs = [
      { name: 'Button', canonicalImport: 'ButtonBridge', hasDefaultSlot: true, namedSlots: [], props: [{ name: 'size', tsType: `'M'|'L'` }] },
      { name: 'Notification', canonicalImport: 'Notification', hasDefaultSlot: false, namedSlots: [], props: [{ name: 'closable', tsType: 'boolean' }] },
      { name: 'Switch', canonicalImport: 'Switch', hasDefaultSlot: false, namedSlots: [], props: [{ name: 'enable', tsType: `'yes'|'no'` }] },
    ]
    const inScope = deriveInScope(cfgs).map(c => c.name)
    expect(inScope).toContain('Button')
    expect(inScope).toContain('Notification')
    expect(inScope).not.toContain('Switch')
  })
})

describe('checkReactDemo', () => {
  it('PASS: boolean bound to writable state + slot children', () => {
    const src = `
      function App(){ const [c,setC]=useState(true); const onx=()=>setC(v=>!v)
        return <><CheckBox onStatusChange={onx}/><PopupBox closable={c}><FormItem label="x"/></PopupBox></> }`
    const r = checkReactDemo(src, POPUPBOX)
    expect(r).toEqual({ used: true, slotOk: true, boolLiveOk: true })
  })
  it('FAIL: static boolean literal (closable) is not live', () => {
    const src = `function App(){ return <Notification closable/> }`
    const r = checkReactDemo(src, NOTIF)
    expect(r.used).toBe(true)
    expect(r.boolLiveOk).toBe(false)
  })
  it('slot N/A component (no slot) reports slotOk true', () => {
    const src = `function App(){ const [c,setC]=useState(true); return <Notification closable={c}/>; setC }`
    expect(checkReactDemo(src, NOTIF).slotOk).toBe(true)
  })
  it('boolean N/A component (Button) reports boolLiveOk true when slot present', () => {
    const src = `function App(){ return <Button size="M">Save</Button> }`
    expect(checkReactDemo(src, BUTTON)).toEqual({ used: true, slotOk: true, boolLiveOk: true })
  })
})

describe('checkVueDemo', () => {
  it('PASS: :closable bound to writable ref + default slot', () => {
    const sfc = `<script setup>import {ref} from 'vue'; const shut=ref(true); function f(){shut.value=!shut.value}</script>
      <template><Switch @click="f"/><PopupBox :closable="shut"><div>body</div></PopupBox></template>`
    expect(checkVueDemo(sfc, POPUPBOX)).toEqual({ used: true, slotOk: true, boolLiveOk: true })
  })
  it('FAIL: :closable="true" literal is not live', () => {
    const sfc = `<script setup></script><template><Notification :closable="true"/></template>`
    expect(checkVueDemo(sfc, NOTIF).boolLiveOk).toBe(false)
  })
})

describe('demos/*.tsx parsing', () => {
  it('Button slot projection in demos/Button.tsx satisfies checkReactDemo', () => {
    const demosDir = resolve(__dirname, '..', 'react-pilot', 'src', 'demos')
    expect(existsSync(demosDir)).toBe(true)

    const demoFiles = readdirSync(demosDir).filter(f => f.endsWith('.tsx'))
    expect(demoFiles).toContain('Button.tsx')

    const buttonSrc = readFileSync(resolve(demosDir, 'Button.tsx'), 'utf8')
    const result = checkReactDemo(buttonSrc, BUTTON)
    // Button has no boolProps, only needs slot projection
    expect(result.used).toBe(true)
    expect(result.slotOk).toBe(true)
    expect(result.boolLiveOk).toBe(true)
  })
})
