import { program } from 'commander'

import color from 'kleur'
import {
  cleanApp,
  configShow,
  diffApp,
  envList,
  envRm,
  envSet,
  getApp,
  infoApp,
  listApps,
  logApp,
  newApp,
  openApp,
  pullApp,
  pushApp,
  renameApp,
  restartApp,
  rmApp,
  rollbackApp,
  stashApp,
  stashListApp,
  stashPopApp,
  startApp,
  statusApp,
  stopApp,
  syncApp,
  versionsApp,
} from './commands'

program
  .name('toes')
  .version('v0.0.4', '-v, --version')
  .addHelpText('beforeAll', (ctx) => {
    if (ctx.command === program) {
      return color.bold().cyan('\n🐾 Toes') + color.gray(' - personal web appliance\n')
    }
    return ''
  })
  .configureOutput({
    writeOut: (str) => {
      const colored = str
        .replace(/^(Usage:)/gm, color.yellow('$1'))
        .replace(/^(Commands:)/gm, color.yellow('$1'))
        .replace(/^(Options:)/gm, color.yellow('$1'))
        .replace(/^(Arguments:)/gm, color.yellow('$1'))
      process.stdout.write(colored)
    },
  })

program
  .command('version', { hidden: true })
  .action(() => console.log(program.version()))

program
  .command('config')
  .description('Show current host configuration')
  .action(configShow)

program
  .command('info')
  .description('Show info for an app')
  .argument('[name]', 'app name (uses current directory if omitted)')
  .action(infoApp)

program
  .command('list')
  .description('List all apps')
  .option('-t, --tools', 'show only tools')
  .option('-a, --all', 'show all apps including tools')
  .action(listApps)

program
  .command('start')
  .description('Start an app')
  .argument('[name]', 'app name (uses current directory if omitted)')
  .action(startApp)

program
  .command('stop')
  .description('Stop an app')
  .argument('[name]', 'app name (uses current directory if omitted)')
  .action(stopApp)

program
  .command('restart')
  .description('Restart an app')
  .argument('[name]', 'app name (uses current directory if omitted)')
  .action(restartApp)

program
  .command('logs')
  .description('Show logs for an app')
  .argument('[name]', 'app name (uses current directory if omitted)')
  .option('-f, --follow', 'follow log output')
  .option('-d, --date <date>', 'show logs from a specific date (YYYY-MM-DD)')
  .option('-s, --since <duration>', 'show logs since duration (e.g., 1h, 2d)')
  .option('-g, --grep <pattern>', 'filter logs by pattern')
  .action(logApp)

program
  .command('log', { hidden: true })
  .argument('[name]', 'app name (uses current directory if omitted)')
  .option('-f, --follow', 'follow log output')
  .option('-d, --date <date>', 'show logs from a specific date (YYYY-MM-DD)')
  .option('-s, --since <duration>', 'show logs since duration (e.g., 1h, 2d)')
  .option('-g, --grep <pattern>', 'filter logs by pattern')
  .action(logApp)

program
  .command('open')
  .description('Open an app in browser')
  .argument('[name]', 'app name (uses current directory if omitted)')
  .action(openApp)

program
  .command('get')
  .description('Download an app from server')
  .argument('<name>', 'app name')
  .action(getApp)

program
  .command('new')
  .description('Create a new toes app')
  .argument('[name]', 'app name (uses current directory if omitted)')
  .option('--ssr', 'SSR template with pages directory (default)')
  .option('--bare', 'minimal template with no pages')
  .option('--spa', 'single-page app with client-side rendering')
  .action(newApp)

program
  .command('push')
  .description('Push local changes to server')
  .action(pushApp)

program
  .command('pull')
  .description('Pull changes from server')
  .option('-f, --force', 'overwrite local changes')
  .action(pullApp)

program
  .command('status')
  .description('Show what would be pushed/pulled')
  .action(statusApp)

program
  .command('diff')
  .description('Show diff of changed files')
  .action(diffApp)

program
  .command('sync')
  .description('Watch and sync changes bidirectionally')
  .action(syncApp)

program
  .command('clean')
  .description('Remove local files not on server')
  .option('-f, --force', 'skip confirmation')
  .option('-n, --dry-run', 'show what would be removed')
  .action(cleanApp)

const stash = program
  .command('stash')
  .description('Stash local changes')
  .action(stashApp)

stash
  .command('pop')
  .description('Restore stashed changes')
  .action(stashPopApp)

stash
  .command('list')
  .description('List all stashes')
  .action(stashListApp)

const env = program
  .command('env')
  .description('Manage environment variables')
  .argument('[name]', 'app name (uses current directory if omitted)')
  .action(envList)

env
  .command('set')
  .description('Set an environment variable')
  .argument('[name]', 'app name (uses current directory if omitted)')
  .argument('<key>', 'variable name')
  .argument('[value]', 'variable value (or use KEY=value format)')
  .action(envSet)

env
  .command('rm')
  .description('Remove an environment variable')
  .argument('[name]', 'app name (uses current directory if omitted)')
  .argument('<key>', 'variable name to remove')
  .action(envRm)

program
  .command('versions')
  .description('List deployed versions')
  .argument('[name]', 'app name (uses current directory if omitted)')
  .action(versionsApp)

program
  .command('rollback')
  .description('Rollback to a previous version')
  .argument('[name]', 'app name (uses current directory if omitted)')
  .option('-v, --version <version>', 'version to rollback to (prompts if omitted)')
  .action((name, options) => rollbackApp(name, options.version))

program
  .command('rm')
  .description('Remove an app from the server')
  .argument('[name]', 'app name (uses current directory if omitted)')
  .action(rmApp)

program
  .command('rename')
  .description('Rename an app')
  .argument('[name]', 'app name (uses current directory if omitted)')
  .argument('<new-name>', 'new app name')
  .action(renameApp)

export { program }
