#!/usr/bin/env tsx
import * as fs from "fs"
import * as path from "path"
import { iconLibraries, type IconLibraryName } from "shadcn/icons"

type IconUsage = Record<IconLibraryName, Set<string>>

function findTsxFiles(dir: string) {
  const files: string[] = []
  const entries = fs.readdirSync(dir, { withFileTypes: true })

  for (const entry of entries) {
    const fullPath = path.join(dir, entry.name)
    if (entry.isDirectory()) {
      files.push(...findTsxFiles(fullPath))
    } else if (entry.isFile() && entry.name.endsWith(".tsx")) {
      files.push(fullPath)
    }
  }

  return files
}

function scanIconUsage() {
  const iconUsage: IconUsage = Object.keys(iconLibraries).reduce((acc, key) => {
    acc[key as IconLibraryName] = new Set()
    return acc
  }, {} as IconUsage)

  const registryBasesDir = path.join(process.cwd(), "registry/bases")
  const files = findTsxFiles(registryBasesDir)
  const libraryNames = Object.values(iconLibraries)
    .map((lib) => lib.name)
    .join("|")
  const iconPlaceholderRegex = new RegExp(
    `<IconPlaceholder\\s+([^>]*?)(?:${libraryNames})=["']([^"']+)["']([^>]*?)\\/?>`,
    "g"
  )

  for (const file of files) {
    const content = fs.readFileSync(file, "utf-8")

    let match
    while ((match = iconPlaceholderRegex.exec(content)) !== null) {
      const fullMatch = match[0]

      for (const [libraryName, config] of Object.entries(iconLibraries)) {
        const attrMatch = fullMatch.match(
          new RegExp(`${config.name}=["']([^"']+)["']`)
        )
        if (attrMatch) {
          iconUsage[libraryName as IconLibraryName].add(attrMatch[1])
        }
      }
    }
  }

  return iconUsage
}

function generateIconFiles(iconUsage: IconUsage) {
  const outputDir = path.join(process.cwd(), "registry/icons")

  console.log("✓ Generated icon files:")

  Object.entries(iconLibraries).forEach(([libraryName, config]) => {
    const icons = Array.from(iconUsage[libraryName as IconLibraryName]).sort()

    if (icons.length === 0) {
      return
    }

    const content = `// Auto-generated by scripts/build-icons.ts
${icons.map((icon) => `export { ${icon} } from "${config.export}"`).join("\n")}
`

    const filename = `__${libraryName}__.ts`
    fs.writeFileSync(path.join(outputDir, filename), content)

    console.log(`  - ${config.title}: ${icons.length} icons`)
  })
}

function main() {
  const iconUsage = scanIconUsage()
  generateIconFiles(iconUsage)
}

const isWatchMode = process.argv.includes("--watch")

if (isWatchMode) {
  const REGISTRY_DIR = path.join(process.cwd(), "registry/bases")

  async function startWatcher() {
    const { default: chokidar } = await import("chokidar")

    main()

    const watcher = chokidar.watch(REGISTRY_DIR, {
      ignored: /(^|[/\\])\../,
      persistent: true,
      ignoreInitial: true,
    })

    const rebuild = (filename: string) => {
      if (!filename.endsWith(".tsx")) return

      try {
        main()
      } catch (error) {
        console.error("❌ Icons build failed:", error)
      }
    }

    watcher.on("error", (error) => {
      console.error("❌ Watcher error:", error)
    })

    watcher.on("change", rebuild)
    watcher.on("add", rebuild)

    process.on("SIGINT", async () => {
      await watcher.close()
      process.exit(0)
    })
  }

  startWatcher()
} else {
  main()
}
