import { DEFAULT_EMOJI } from '@types'
import { readdirSync, readFileSync, statSync } from 'fs'
import { join, relative } from 'path'

export type TemplateType = 'ssr' | 'bare' | 'spa'

export type AppTemplates = Record<string, string>

interface TemplateOptions {
  tool?: boolean
}

interface TemplateVars {
  APP_EMOJI: string
  APP_NAME: string
}

const SHARED_FILES = ['CLAUDE.md', '.gitignore', '.npmrc', 'package.json', 'tsconfig.json']
const TEMPLATES_DIR = join(import.meta.dir, '../../templates')

function readDir(dir: string): string[] {
  const files: string[] = []
  for (const entry of readdirSync(dir)) {
    const path = join(dir, entry)
    if (statSync(path).isDirectory()) {
      files.push(...readDir(path))
    } else {
      files.push(path)
    }
  }
  return files
}

function replaceVars(content: string, vars: TemplateVars): string {
  return content
    .replace(/\$\$APP_NAME\$\$/g, vars.APP_NAME)
    .replace(/\$\$APP_EMOJI\$\$/g, vars.APP_EMOJI)
}

export function generateTemplates(appName: string, template: TemplateType = 'ssr', options: TemplateOptions = {}): AppTemplates {
  const vars: TemplateVars = {
    APP_EMOJI: DEFAULT_EMOJI,
    APP_NAME: appName,
  }

  const result: AppTemplates = {}

  // Read shared files from templates/
  for (const filename of SHARED_FILES) {
    const path = join(TEMPLATES_DIR, filename)
    let content = readFileSync(path, 'utf-8')
    content = replaceVars(content, vars)

    // Add tool option to package.json if specified
    if (filename === 'package.json' && options.tool) {
      const pkg = JSON.parse(content)
      pkg.toes.tool = true
      content = JSON.stringify(pkg, null, 2) + '\n'
    }

    result[filename] = content
  }

  // Read template-specific files
  const templateDir = join(TEMPLATES_DIR, template)
  for (const path of readDir(templateDir)) {
    const filename = relative(templateDir, path)
    const content = readFileSync(path, 'utf-8')
    result[filename] = replaceVars(content, vars)
  }

  return result
}
