import { writeFileSync } from 'node:fs'
import { basename, join } from 'node:path'
import { globby } from 'globby'

const rootDir = join(import.meta.dirname, '../..')

/**
 * Convert example file name to PascalCase export name
 * e.g., 'basic.tsx' -> 'Basic', 'root-provider.tsx' -> 'RootProvider'
 */
function toExportName(fileName: string): string {
  return fileName
    .replace('.tsx', '')
    .split('-')
    .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
    .join('')
}

/**
 * Convert file path to a unique import alias
 * e.g., 'menu/examples/basic.tsx' -> 'Menu_Basic'
 */
function toImportAlias(componentName: string, exampleName: string): string {
  const component = componentName
    .split('-')
    .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
    .join('')
  const example = toExportName(exampleName)
  return `${component}_${example}`
}

const main = async () => {
  // Find all example files in React components
  const exampleFiles = await globby(['packages/react/src/components/*/examples/*.tsx'], {
    cwd: rootDir,
  })

  // Also find nested examples (like progress/examples/circular/*.tsx)
  const nestedExampleFiles = await globby(['packages/react/src/components/*/examples/*/*.tsx'], {
    cwd: rootDir,
  })

  // Also find provider examples
  const providerExampleFiles = await globby(['packages/react/src/providers/*/examples/*.tsx'], {
    cwd: rootDir,
  })

  const allFiles = [...exampleFiles, ...nestedExampleFiles, ...providerExampleFiles]

  // Group by component
  const imports: string[] = []
  const registryEntries: string[] = []

  for (const file of allFiles.sort()) {
    // Parse the file path to extract component and example names
    // e.g., 'packages/react/src/components/menu/examples/basic.tsx'
    const parts = file.split('/')
    const exampleFileName = basename(file)

    // Skip template files
    if (exampleFileName.startsWith('_')) continue

    // Handle different path structures
    let componentName: string
    let exampleKey: string

    if (file.includes('/providers/')) {
      // Provider examples: providers/environment/examples/basic.tsx
      const providerIdx = parts.indexOf('providers')
      componentName = parts[providerIdx + 1]
      exampleKey = exampleFileName.replace('.tsx', '')
    } else if (parts.includes('examples') && parts[parts.indexOf('examples') + 1]?.includes('.tsx')) {
      // Standard examples: components/menu/examples/basic.tsx
      const examplesIdx = parts.indexOf('examples')
      componentName = parts[examplesIdx - 1]
      exampleKey = exampleFileName.replace('.tsx', '')
    } else {
      // Nested examples: components/progress/examples/circular/basic.tsx
      const examplesIdx = parts.indexOf('examples')
      componentName = parts[examplesIdx - 1]
      const subFolder = parts[examplesIdx + 1]
      // Use subfolder as part of example key for nested examples
      exampleKey = `${subFolder}/${exampleFileName.replace('.tsx', '')}`
    }

    // Use namespace import to avoid export name guessing
    const importAlias = toImportAlias(
      componentName + (exampleKey.includes('/') ? '-' + exampleKey.split('/')[0] : ''),
      exampleFileName,
    )

    // Use @examples alias configured in next.config.mjs
    // @examples points to packages/react/src/components
    let importPath: string
    if (file.includes('/providers/')) {
      // Provider examples need different path
      const providerIdx = parts.indexOf('providers')
      const rest = parts
        .slice(providerIdx + 1)
        .join('/')
        .replace('.tsx', '')
      importPath = `../../../packages/react/src/providers/${rest}`
    } else {
      // Use @examples alias for component examples
      const componentsIdx = parts.indexOf('components')
      const rest = parts
        .slice(componentsIdx + 1)
        .join('/')
        .replace('.tsx', '')
      importPath = `@examples/${rest}`
    }

    // Use namespace import (import * as X) to get all exports
    imports.push(`import * as ${importAlias} from '${importPath}'`)
    registryEntries.push(`  '${componentName}/${exampleKey}': ${importAlias}`)
  }

  // Generate the registry file
  const output = `// AUTO-GENERATED FILE - DO NOT EDIT
// Generated by scripts/src/generate-example-registry.ts
// Run: pnpm --filter scripts generate-example-registry

import type { ComponentType } from 'react'

${imports.join('\n')}

// Registry maps example keys to their module namespace
// Each module is imported as a namespace (import * as X) to handle varying export names
type ExampleModule = Record<string, unknown>

const exampleModules: Record<string, ExampleModule> = {
${registryEntries.join(',\n')}
}

/**
 * Get the first component export from a module
 */
function getComponentFromModule(mod: ExampleModule): ComponentType | undefined {
  // Find the first function/component export (skip type exports)
  for (const key of Object.keys(mod)) {
    const value = mod[key]
    if (typeof value === 'function') {
      return value as ComponentType
    }
  }
  return undefined
}

/**
 * Get an example component by component name and example id
 */
export function getExample(component: string, example: string): ComponentType | undefined {
  const mod = exampleModules[\`\${component}/\${example}\`]
  if (!mod) return undefined
  return getComponentFromModule(mod)
}

/**
 * Check if an example exists
 */
export function hasExample(component: string, example: string): boolean {
  return \`\${component}/\${example}\` in exampleModules
}
`

  // Write to website/src/lib/example-registry.ts
  const outputPath = join(rootDir, 'website/src/lib/example-registry.ts')
  writeFileSync(outputPath, output)

  console.log(`Generated example registry with ${allFiles.length} examples`)
  console.log(`Output: ${outputPath}`)
}

main().catch((err) => {
  console.error(err.message)
  process.exit(1)
})
