import fs from 'node:fs'
import path from 'node:path'
import { createRequire } from 'node:module'
import { execSync } from 'node:child_process'

const require = createRequire(import.meta.url)
let ts
try {
  ts = require('typescript')
} catch {
  try {
    const globalRoot = execSync('npm root -g', { encoding:'utf8' }).trim()
    ts = require(path.join(globalRoot, 'typescript'))
  } catch {
    console.log('TypeScript is not installed yet; syntax transpile gate is deferred to pnpm typecheck.')
    process.exit(0)
  }
}

const root = process.cwd()
function walk(dir) {
  if (!fs.existsSync(dir)) return []
  return fs.readdirSync(dir,{withFileTypes:true}).flatMap(e => e.isDirectory() ? walk(path.join(dir,e.name)) : [path.join(dir,e.name)])
}
let count = 0
const failures = []
for (const file of walk(root)) {
  if (file.includes('/node_modules/')) continue
  let source = null
  if (file.endsWith('.ts')) source = fs.readFileSync(file,'utf8')
  else if (file.endsWith('.vue')) {
    const text = fs.readFileSync(file,'utf8')
    const match = text.match(/<script setup[^\n]*>\s*([\s\S]*?)<\/script>/)
    if (match) source = match[1]
  }
  if (source == null) continue
  const result = ts.transpileModule(source, {
    compilerOptions: { target: ts.ScriptTarget.ES2022, module: ts.ModuleKind.ESNext },
    reportDiagnostics: true,
    fileName: file + (file.endsWith('.vue') ? '.ts' : ''),
  })
  const diagnostics = (result.diagnostics ?? []).filter(x => x.category === ts.DiagnosticCategory.Error)
  if (diagnostics.length) failures.push({ file: path.relative(root,file), diagnostics: diagnostics.map(x => ts.flattenDiagnosticMessageText(x.messageText, ' ')) })
  count++
}
if (failures.length) {
  console.error(JSON.stringify(failures, null, 2))
  process.exit(1)
}
console.log(`TypeScript syntax transpile passed for ${count} TS/Vue script units.`)
