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

const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..')

const EXCLUDE_DIRS = new Set([
  'node_modules',
  '.vitepress',
  'server',
  'assets',
  'images',
  '.git',
  '金瓶梅',
  '黄帝内经',
  '健康学习到150岁 - 人体系统调优不完全指南',
  '梅花',
])

type SidebarItem = {
  text: string
  link?: string
  collapsed?: boolean
  items?: SidebarItem[]
}

function naturalCompare(a: string, b: string) {
  return a.localeCompare(b, 'zh-CN', { numeric: true, sensitivity: 'base' })
}

function titleFromFilename(name: string) {
  const base = name.replace(/\.md$/i, '')
  if (/^readme$/i.test(base)) return '导读'
  return base
}

function toLink(relativePath: string) {
  const normalized = relativePath.replace(/\\/g, '/').replace(/\.md$/i, '')
  if (normalized.endsWith('/README')) {
    return `/${normalized.slice(0, -'/README'.length)}/`
  }
  return `/${normalized}`
}

function collectItems(dir: string, relativeDir: string): SidebarItem[] {
  const entries = fs.readdirSync(dir, { withFileTypes: true })
  const files = entries.filter((entry) => entry.isFile() && entry.name.endsWith('.md'))
  const subdirs = entries.filter((entry) => entry.isDirectory())

  const items: SidebarItem[] = files
    .sort((a, b) => naturalCompare(a.name, b.name))
    .map((file) => ({
      text: titleFromFilename(file.name),
      link: toLink(path.join(relativeDir, file.name)),
    }))

  for (const subdir of subdirs.sort((a, b) => naturalCompare(a.name, b.name))) {
    const subRelative = path.join(relativeDir, subdir.name)
    const subItems = collectItems(path.join(dir, subdir.name), subRelative)
    if (subItems.length === 0) continue
    items.push({
      text: subdir.name,
      collapsed: true,
      items: subItems,
    })
  }

  return items
}

export function generateSidebar(): Record<string, SidebarItem[]> {
  const groups: SidebarItem[] = []

  const rootFiles = fs
    .readdirSync(root, { withFileTypes: true })
    .filter(
      (entry) =>
        entry.isFile() &&
        entry.name.endsWith('.md') &&
        entry.name !== 'README.md' &&
        entry.name !== 'index.md',
    )
    .sort((a, b) => naturalCompare(a.name, b.name))

  if (rootFiles.length > 0) {
    groups.push({
      text: '典籍',
      collapsed: true,
      items: rootFiles.map((file) => ({
        text: titleFromFilename(file.name),
        link: toLink(file.name),
      })),
    })
  }

  const dirs = fs
    .readdirSync(root, { withFileTypes: true })
    .filter((entry) => entry.isDirectory() && !EXCLUDE_DIRS.has(entry.name))
    .sort((a, b) => naturalCompare(a.name, b.name))

  for (const dir of dirs) {
    const items = collectItems(path.join(root, dir.name), dir.name)
    if (items.length === 0) continue
    groups.push({
      text: dir.name,
      collapsed: true,
      items,
    })
  }

  return { '/': groups }
}
