#!/usr/bin/env node
/**
 * Scaffold per-component playground pages.
 *
 * Reads docs/ai-summary.json and, for every component under
 * src/runtime/components/, emits:
 *   - playground/pages/components/<slug>.vue   (stub demo + API panel)
 *   - playground/playgrounds.generated.ts      (component registry array)
 *
 * Idempotency: pages start with a "SCAFFOLD_MARKER" comment. The script
 * overwrites only files that still carry the marker — hand-edited pages
 * (marker removed) are left alone.
 *
 * Run with: pnpm exec node scripts/scaffold-playground-pages.mjs
 */
import fs from 'node:fs'
import path from 'node:path'

const rootDir = process.cwd()
const aiSummary = JSON.parse(fs.readFileSync(path.join(rootDir, 'docs/ai-summary.json'), 'utf8'))
const pagesDir = path.join(rootDir, 'playground/pages/components')
const registryFile = path.join(rootDir, 'playground/playgrounds.generated.ts')

const SCAFFOLD_MARKER = '<!-- SCAFFOLD: auto-generated by scripts/scaffold-playground-pages.mjs. Delete this line to opt out of overwrites. -->'

function pascal(segment) {
  return segment.charAt(0).toUpperCase() + segment.slice(1)
}

function deriveNames(componentPath) {
  // componentPath like "src/runtime/components/form/images/Pad.vue"
  const rel = componentPath.replace(/^src\/runtime\/components\//, '').replace(/\.vue$/, '')
  const segments = rel.split('/')
  const componentName = segments.map(pascal).join('')
  const slug = segments.map(s => s.toLowerCase()).join('-')
  const title = componentName
  // First path segment is the group; root-level components fall into "general".
  const group = segments.length > 1 ? segments[0].toLowerCase() : 'general'
  return { componentName, slug, title, group }
}

function renderPage({ componentName, title, summary, sourcePath }) {
  const props = inferStubProps(componentName)
  const propsAttr = props ? ' ' + props : ''
  const setup = setupForComponent[componentName] ?? ''
  return `<script setup lang="ts">
// ${SCAFFOLD_MARKER.replace(/^<!--\s*|\s*-->$/g, '')}
//
// To enrich this page (richer demo, multiple variants, controls, etc.),
// remove the SCAFFOLD comment in the <template> below — the scaffold
// script will then leave this file alone on future runs.
${setup}</script>

<template>
  ${SCAFFOLD_MARKER}
  <PlaygroundPage
    title="${title}"
    summary="${escapeAttr(summary)}"
    source-path="${sourcePath}"
  >
    <div class="text-caption text-medium-emphasis mb-3">
      Auto-scaffolded demo — mounts the component with minimal props.
      Replace this block (and delete the SCAFFOLD comment) when you wire
      up a realistic interactive demo.
    </div>
    <${componentName}${propsAttr} />
  </PlaygroundPage>
</template>
`
}

function escapeAttr(s) {
  return (s || '').replace(/"/g, '&quot;').replace(/\n/g, ' ')
}

/**
 * Hand-tuned minimal props for components that throw without them.
 * Keep tiny — anything richer belongs in a hand-enriched page.
 */
const stubProps = {
  FormTable: 'title="Demo table"',
  FormTableData: 'title="Demo table"',
  FormActionPad: 'title="Demo"',
  FormEditPad: 'title="Demo"',
  FormSystem: 'name="demoForm"',
  FormDialog: ':model-value="false" title="Demo"',
  FormImagesCapture: 'title="Demo"',
  FormImagesEdit: 'title="Demo"',
  FormImagesField: 'title="Demo"',
  FormImagesPad: 'title="Demo"',
  DialogConfirm: ':model-value="false"',
  DialogLoading: ':model-value="false"',
  DialogIndex: ':model-value="false" title="Demo"',
  DialogHost: '',
  DialogDefaultConfirm: ':model-value="false"',
  DialogDefaultLoading: ':model-value="false"',
  DialogDefaultNotify: ':model-value="false"',
  DialogDefaultPrinting: ':model-value="false"',
  DialogDefaultVerifyUser: ':model-value="false"',
  DocumentForm: 'documentName="demo"',
  DocumentTemplateBuilder: 'title="Template Builder"',
  ModelTable: 'modelName="MasterItem" :fields="[\'*\']"',
  ModelPad: 'modelName="MasterItem"',
  ModelIterator: 'modelName="MasterItem" :fields="[\'*\']"',
  ModelLabel: 'modelName="MasterItem"',
  ModelSelect: 'modelName="MasterItem"',
  ModelAutocomplete: 'modelName="MasterItem"',
  ModelCombobox: 'modelName="MasterItem"',
  MasterLabel: 'groupKey="DEMO"',
  MasterSelect: 'groupKey="DEMO"',
  MasterAutocomplete: 'groupKey="DEMO"',
  MasterCombobox: 'groupKey="DEMO"',
  MasterRadioGroup: 'groupKey="DEMO"',
  LabelDate: 'model-value="2026-05-18"',
  LabelDateAgo: ':model-value="DateTime.now()"',
  LabelDateCount: ':model-value="DateTime.now()"',
  LabelField: 'label="Demo" model-value="value"',
  LabelFormatMoney: ':model-value="1234.5"',
  LabelMask: 'mask="###-###-####" model-value="1234567890"',
  LabelObject: ':model-value="{ key: \'value\' }"',
  PdfView: '',
  PdfPrint: '',
  SplitterPanel: '',
  TabsGroup: ':items="[{ label: \'Tab 1\' }, { label: \'Tab 2\' }]"',
  ImportCSV: '',
  ExportCSV: ':model-value="[]" file-name="demo"',
  FileBtn: 'label="Upload"',
  BarcodeReader: '',
  MrzReader: '',
  TextBarcode: ':model-value="\'ABC123\'"',
  Alert: '',
  DeviceIdCardButton: '',
  DeviceIdCardWebSocket: '',
  DeviceScanner: '',
  FormLogin: '',
  FormPad: '',
  FormBirthdate: '',
  FormCheckboxGroup: ':items="[{ title: \'One\', value: 1 }, { title: \'Two\', value: 2 }]"',
  FormCodeEditor: 'language="javascript"',
  FormDate: '',
  FormDateTime: '',
  FormTime: '',
  FormFile: '',
  FormHidden: '',
  FormIterator: '',
  FormSignPad: '',
}

function inferStubProps(componentName) {
  return stubProps[componentName] ?? ''
}

/** Per-component <script setup> snippets injected after the SCAFFOLD comment. */
const setupForComponent = {
  LabelDateAgo: `import { DateTime } from 'luxon'\n`,
  LabelDateCount: `import { DateTime } from 'luxon'\n`,
}

function shouldOverwrite(filePath) {
  if (!fs.existsSync(filePath)) return true
  const content = fs.readFileSync(filePath, 'utf8')
  return content.includes(SCAFFOLD_MARKER)
}

const entries = []
let written = 0
let skipped = 0

for (const component of aiSummary.components) {
  const { componentName, slug, title, group } = deriveNames(component.path)
  const summary = (component.summary || '').replace(/"/g, '\'')
  const sourcePath = component.path

  const subdir = slug.includes('-') ? '' : '' // flat layout under components/
  const fileName = `${slug}.vue`
  const filePath = path.join(pagesDir, subdir, fileName)
  fs.mkdirSync(path.dirname(filePath), { recursive: true })

  if (shouldOverwrite(filePath)) {
    fs.writeFileSync(filePath, renderPage({ componentName, title, summary, sourcePath }))
    written++
  }
  else {
    skipped++
  }

  entries.push({
    slug,
    title,
    summary,
    to: `/components/${slug}`,
    group,
  })
}

entries.sort((a, b) => a.slug.localeCompare(b.slug))

const registrySource = `// Auto-generated by scripts/scaffold-playground-pages.mjs.
// Do not edit by hand — re-run the script after adding components.
import type { PlaygroundEntry } from './playgrounds'

export const componentEntries: PlaygroundEntry[] = ${JSON.stringify(entries, null, 2)}
`
fs.writeFileSync(registryFile, registrySource)

console.log(`Pages scaffolded: ${written} written, ${skipped} preserved (hand-edited).`)
console.log(`Registry: ${path.relative(rootDir, registryFile)} (${entries.length} entries)`)
