import fs from 'node:fs'
import path from 'node:path'
import vm from 'node:vm'
import { fileURLToPath } from 'node:url'

const __dirname = path.dirname(fileURLToPath(import.meta.url))
const rootDir = path.resolve(__dirname, '..')
const dataDir = path.join(rootDir, 'src', 'data')
const apiDir = path.join(rootDir, 'public', 'api')
const apiDocPath = path.join(rootDir, 'public', 'apidoc')

function readJson(relativePath) {
  return JSON.parse(fs.readFileSync(path.join(rootDir, relativePath), 'utf8'))
}

function ensureDir(dir) {
  fs.mkdirSync(dir, { recursive: true })
}

function writeJson(relativePath, data) {
  const target = path.join(apiDir, relativePath)
  ensureDir(path.dirname(target))
  fs.writeFileSync(target, `${JSON.stringify(data, null, 2)}\n`, 'utf8')
}

function cleanApiDir() {
  fs.rmSync(apiDir, { recursive: true, force: true })
  fs.rmSync(apiDocPath, { force: true })
  ensureDir(apiDir)
}

function writeTextFile(target, content) {
  ensureDir(path.dirname(target))
  fs.writeFileSync(target, content, 'utf8')
}

function copyApiDoc() {
  const source = path.join(rootDir, 'docs', '知识库API接口说明.md')
  const content = fs.readFileSync(source, 'utf8')
  writeTextFile(apiDocPath, content)
}

function extractConstArrayFromTs(filePath, constName) {
  const text = fs.readFileSync(filePath, 'utf8')
  const marker = `export const ${constName}`
  const markerIndex = text.indexOf(marker)
  if (markerIndex === -1) {
    throw new Error(`未找到 ${constName}`)
  }

  const assignmentIndex = text.indexOf('=', markerIndex)
  if (assignmentIndex === -1) {
    throw new Error(`未找到 ${constName} 赋值符号`)
  }

  const arrayStart = text.indexOf('[', assignmentIndex)
  if (arrayStart === -1) {
    throw new Error(`未找到 ${constName} 数组起点`)
  }

  let depth = 0
  let quote = null
  let escaped = false
  let lineComment = false
  let blockComment = false

  for (let index = arrayStart; index < text.length; index += 1) {
    const char = text[index]
    const next = text[index + 1]

    if (lineComment) {
      if (char === '\n') lineComment = false
      continue
    }

    if (blockComment) {
      if (char === '*' && next === '/') {
        blockComment = false
        index += 1
      }
      continue
    }

    if (quote) {
      if (escaped) {
        escaped = false
      } else if (char === '\\') {
        escaped = true
      } else if (char === quote) {
        quote = null
      }
      continue
    }

    if (char === '/' && next === '/') {
      lineComment = true
      index += 1
      continue
    }

    if (char === '/' && next === '*') {
      blockComment = true
      index += 1
      continue
    }

    if (char === '\'' || char === '"' || char === '`') {
      quote = char
      continue
    }

    if (char === '[') depth += 1
    if (char === ']') {
      depth -= 1
      if (depth === 0) {
        const source = text.slice(arrayStart, index + 1)
        return vm.runInNewContext(`(${source})`, {}, { timeout: 1000 })
      }
    }
  }

  throw new Error(`未能完整解析 ${constName}`)
}

const knowledgeAreas = readJson('src/data/knowledge-areas.json').knowledgeAreas
const processGroups = readJson('src/data/process-groups.json').processGroups
const processes = readJson('src/data/processes.json').processes
const artifacts = readJson('src/data/artifacts.json').artifacts
const tools = readJson('src/data/tools.json').tools
const performanceDomains = extractConstArrayFromTs(
  path.join(dataDir, 'performance-domains.ts'),
  'performanceDomains'
)

const knowledgeAreaMap = new Map(knowledgeAreas.map((item) => [item.id, item]))
const processGroupMap = new Map(processGroups.map((item) => [item.id, item]))
const artifactMap = new Map(artifacts.map((item) => [item.id, item]))
const toolMap = new Map(tools.map((item) => [item.id, item]))

function normalizeRef(ref) {
  if (typeof ref === 'string') return { id: ref, details: [], note: undefined }
  return {
    id: ref.id,
    details: Array.isArray(ref.detail) ? ref.detail.map((item) => ({ label: item.label })) : [],
    note: ref.note,
  }
}

function processSummary(process) {
  const knowledgeArea = knowledgeAreaMap.get(process.knowledgeAreaId)
  const processGroup = processGroupMap.get(process.processGroupId)
  return {
    id: process.id,
    name: process.name,
    knowledgeAreaId: process.knowledgeAreaId,
    knowledgeAreaName: knowledgeArea?.name ?? '',
    processGroupId: process.processGroupId,
    processGroupName: processGroup?.name ?? '',
    purpose: process.purpose ?? '',
  }
}

function attachRefMeta(ref, entityMap) {
  const normalized = normalizeRef(ref)
  const entity = entityMap.get(normalized.id)
  return {
    id: normalized.id,
    name: entity?.name ?? normalized.id,
    details: normalized.details,
    ...(normalized.note ? { note: normalized.note } : {}),
  }
}

function processItto(process) {
  return {
    id: process.id,
    name: process.name,
    inputs: process.inputs.map((ref) => attachRefMeta(ref, artifactMap)),
    tools: process.tools.map((ref) => attachRefMeta(ref, toolMap)),
    outputs: process.outputs.map((ref) => attachRefMeta(ref, artifactMap)),
  }
}

function includesRef(refs, targetId) {
  return refs.some((ref) => normalizeRef(ref).id === targetId)
}

function artifactUsage(artifact) {
  return {
    id: artifact.id,
    name: artifact.name,
    asInput: processes.filter((process) => includesRef(process.inputs, artifact.id)).map(processSummary),
    asOutput: processes.filter((process) => includesRef(process.outputs, artifact.id)).map(processSummary),
  }
}

function toolUsage(tool) {
  return {
    id: tool.id,
    name: tool.name,
    usedIn: processes.filter((process) => includesRef(process.tools, tool.id)).map(processSummary),
  }
}

cleanApiDir()

writeJson('process-groups.json', processGroups.map((item) => ({ id: item.id, name: item.name })))

writeJson(
  'knowledge-areas.json',
  knowledgeAreas.map((item) => ({
    id: item.id,
    name: item.name,
    tailoringFactors: (item.tailoringFactors ?? []).map((factor) => ({
      title: factor.title,
      description: factor.description,
    })),
  }))
)

for (const knowledgeArea of knowledgeAreas) {
  writeJson(
    `knowledge-areas/${knowledgeArea.id}/tailoring-factors.json`,
    (knowledgeArea.tailoringFactors ?? []).map((factor) => ({
      title: factor.title,
      description: factor.description,
    }))
  )

  writeJson(
    `knowledge-areas/${knowledgeArea.id}/processes.json`,
    processes
      .filter((process) => process.knowledgeAreaId === knowledgeArea.id)
      .map((process) => {
        const summary = processSummary(process)
        return {
          id: summary.id,
          name: summary.name,
          processGroupId: summary.processGroupId,
          processGroupName: summary.processGroupName,
          purpose: summary.purpose,
        }
      })
  )
}

for (const processGroup of processGroups) {
  writeJson(
    `process-groups/${processGroup.id}/processes.json`,
    processes
      .filter((process) => process.processGroupId === processGroup.id)
      .map((process) => {
        const summary = processSummary(process)
        return {
          id: summary.id,
          name: summary.name,
          knowledgeAreaId: summary.knowledgeAreaId,
          knowledgeAreaName: summary.knowledgeAreaName,
          purpose: summary.purpose,
        }
      })
  )
}

writeJson('processes.json', processes.map(processSummary))

for (const process of processes) {
  writeJson(`processes/${process.id}.json`, processSummary(process))
  writeJson(`processes/${process.id}/itto.json`, processItto(process))
}

writeJson('performance-domains.json', performanceDomains.map((item) => ({ id: item.id, name: item.name })))

for (const domain of performanceDomains) {
  writeJson(`performance-domains/${domain.id}.json`, {
    id: domain.id,
    name: domain.name,
    expectedGoals: domain.detail?.expectedGoals ?? [],
    keyPoints: domain.detail?.keyPoints ?? [],
    interactions: domain.detail?.interactions ?? [],
    checks: domain.detail?.checks ?? [],
  })
}

writeJson('artifacts.json', artifacts.map((item) => ({ id: item.id, name: item.name })))
writeJson('tools.json', tools.map((item) => ({ id: item.id, name: item.name })))

for (const artifact of artifacts) {
  writeJson(`artifacts/${artifact.id}/usage.json`, artifactUsage(artifact))
}

for (const tool of tools) {
  writeJson(`tools/${tool.id}/usage.json`, toolUsage(tool))
}

copyApiDoc()

console.log(`已生成静态 API 文件：${path.relative(rootDir, apiDir)}`)
console.log(`已生成 Markdown 接口文档：${path.relative(rootDir, apiDocPath)}`)
