const fs = require('fs')
const path = require('path')
const chalk = require('chalk')
const ora = require('ora')
const { getConfig } = require('../lib/config')
const { listCodeLibraries, getCodeLibrary } = require('../lib/api')

/**
 * Folder segment for a template type (spaces -> underscores, strip unsafe chars).
 * @param {string} type
 * @returns {string}
 */
function sanitizeTypeForPath(type) {
  if (!type || typeof type !== 'string') return 'unknown'
  const cleaned = type.replace(/[/\\:?*"<>|]+/g, '_').replace(/\s+/g, '_').trim()
  return cleaned || 'unknown'
}

/**
 * @param {string} [codeType]
 * @returns {string} file extension without dot
 */
function codeTypeToExt(codeType) {
  const c = (codeType || 'jsx').toLowerCase()
  const map = {
    js: 'js',
    jsx: 'jsx',
    ts: 'ts',
    tsx: 'tsx',
    html: 'html',
  }
  return map[c] || 'jsx'
}

function extractRawCode(code) {
  if (code == null) return ''
  if (typeof code === 'string') return code
  if (typeof code === 'object') {
    return code.raw || code.compiled || ''
  }
  return String(code)
}

/** Safe basename for template id (avoid path traversal / odd names). */
function safeTemplateFileSegment(templateId) {
  const s = String(templateId).replace(/[/\\:?*"<>|]+/g, '_').trim()
  return s || 'template'
}

function folderNameToType(folderName) {
  return String(folderName).replace(/_/g, ' ')
}

/**
 * Pull all templates for an app into a folder tree:
 *   {output}/{type_slug}/{templateId}.{ext}
 *   {output}/{type_slug}/{templateId}.json
 */
async function pullCommand(outputDir, options) {
  const config = getConfig()
  const appId = options.appId || config.defaultAppId
  const outDir = path.resolve(options.output || outputDir || './template-library')

  if (!appId) {
    console.error(chalk.red('Error: App ID is required. Use --app-id or set defaultAppId in config.'))
    process.exit(1)
  }

  const spinner = ora('Fetching template list...').start()

  try {
    const templateLibs = await listCodeLibraries(appId)
    const items = Array.isArray(templateLibs) ? templateLibs : Object.values(templateLibs || {})

    if (items.length === 0) {
      spinner.stop()
      console.log(chalk.yellow('No templates found.'))
      return
    }

    let count = 0
    for (const item of items) {
      const cid = item.id
      if (!cid) {
        console.warn(chalk.yellow('Skipping list entry without id'))
        continue
      }

      spinner.text = `Downloading ${cid}...`
      const full = await getCodeLibrary(appId, cid)
      const templateId =
        full.templateId ||
        full.snippetId ||
        item.templateId ||
        item.snippetId

      if (!templateId) {
        console.warn(chalk.yellow(`Skipping item ${cid}: no template ID`))
        continue
      }

      const safeId = safeTemplateFileSegment(templateId)
      const type = full.type || item.type || 'component'
      const typeDirName = sanitizeTypeForPath(type)
      const dir = path.join(outDir, typeDirName)
      fs.mkdirSync(dir, { recursive: true })

      const codeType = full.codeType || item.codeType || 'jsx'
      const ext = codeTypeToExt(codeType)
      const codeFile = path.join(dir, `${safeId}.${ext}`)
      const raw = extractRawCode(full.code)
      fs.writeFileSync(codeFile, raw, 'utf8')

      const meta = {
        name: full.name || item.name || templateId,
        description: full.description ?? item.description ?? '',
        type,
        image: full.image || item.image || '',
        codeType,
        appType: full.appType || item.appType || 'web',
        templateId,
      }
      fs.writeFileSync(
        path.join(dir, `${safeId}.json`),
        `${JSON.stringify(meta, null, 2)}\n`,
        'utf8',
      )
      count++
    }

    spinner.succeed(chalk.green(`Pulled ${count} template(s) to ${outDir}`))
  } catch (error) {
    spinner.fail(error.message)
    process.exit(1)
  }
}

module.exports = pullCommand
module.exports.sanitizeTypeForPath = sanitizeTypeForPath
module.exports.folderNameToType = folderNameToType
