#!/usr/bin/env node
//
// Refresh the spawn atlas from a ServUO tree, from the command line.
//
//   npm run atlas:import                       # use the configured path
//   npm run atlas:import -- --servuo <path>    # override it for this run
//   npm run atlas:import -- --force            # reimport even if unchanged
//   npm run atlas:import -- --approve          # apply a staged refresh
//   npm run atlas:import -- --status           # report without changing anything
//
// The server does this itself on every boot (see `shardAtlas.refreshOnBoot`), so
// this is for operators who want to apply a map change without a restart, and
// for approving a refresh that was staged because it would remove a facet.
//
// All the logic lives in `src/model/shardAtlas/shardAtlas.model.js`; this file
// is argument parsing and output formatting.

const db = () => require('../src/utils/db')

function parseArgs(argv) {
  const args = {}
  for (let i = 0; i < argv.length; i += 1) {
    const flag = argv[i]
    if (flag === '--servuo') args.servuo = argv[++i]
    else if (flag === '--force') args.force = true
    else if (flag === '--approve') args.approve = true
    else if (flag === '--reject') args.reject = true
    else if (flag === '--status') args.status = true
    else if (flag === '--help' || flag === '-h') args.help = true
  }
  return args
}

const USAGE = `
Refresh the spawn atlas from a ServUO tree.

  node scripts/importSpawnAtlas.js [options]

  --servuo <path>  Use this tree for this run instead of the configured path.
  --force          Reimport even when the source files are unchanged.
  --approve        Apply a refresh that was staged for removing a facet.
  --reject         Keep the current atlas and dismiss the staged refresh.
  --status         Report atlas and source state; change nothing.

With no options this imports only if the tree differs from what is loaded.
`

function describe(result) {
  switch (result.status) {
    case 'skipped':
      return (
        'No ServUO path configured — nothing to import.\n' +
        'Set one with SERVUO_PATH, the admin panel, or --servuo <path>.\n'
      )
    case 'unavailable':
      return `ServUO tree unavailable: ${result.reason}\n`
    case 'unchanged':
      return `Atlas is already up to date${result.reason ? ` (${result.reason})` : ''}.\n`
    case 'needsReview': {
      return (
        'Refresh NOT applied — it would remove ' +
        `${result.removedFacets.length} facet(s): ${result.removedFacets.join(', ')}.\n` +
        'This is what a half-copied or mid-update tree looks like, so it has been\n' +
        'staged for review. The current atlas is unchanged.\n' +
        'Apply it with --approve, or dismiss it with --reject.\n'
      )
    }
    case 'imported': {
      const c = result.counts
      const added = result.addedFacets?.length ? ` Added facets: ${result.addedFacets.join(', ')}.` : ''
      const removed = result.removedFacets?.length
        ? ` Removed facets: ${result.removedFacets.join(', ')}.`
        : ''
      return (
        `Atlas imported: ${c.points} points, ${c.creatures} creatures, ` +
        `${c.pointTypes} point/type rows, ${c.regions} regions, ` +
        `${c.landmarks} landmarks, ${c.champions} champion altars.${added}${removed}\n`
      )
    }
    case 'failed':
      return `Atlas refresh failed: ${result.reason}\n`
    default:
      return `${JSON.stringify(result, null, 2)}\n`
  }
}

async function main() {
  const args = parseArgs(process.argv.slice(2))
  if (args.help) {
    process.stdout.write(USAGE)
    return
  }

  const shardAtlas = require('../src/model/shardAtlas/shardAtlas.model')

  // `--servuo` is a per-run override and deliberately does NOT persist to the
  // configured path; changing where the atlas permanently reads from is an
  // admin action, not a side effect of a one-off import.
  const override = { path: args.servuo ?? '' }

  if (args.status) {
    process.stdout.write(`${JSON.stringify(await shardAtlas.status(override), null, 2)}\n`)
    return
  }
  if (args.reject) {
    process.stdout.write(`${JSON.stringify(await shardAtlas.rejectPending(), null, 2)}\n`)
    return
  }

  const result = args.approve
    ? await shardAtlas.approvePending(override)
    : await shardAtlas.refresh({ ...override, force: Boolean(args.force) })

  process.stdout.write(describe(result))
  if (result.status === 'failed') process.exitCode = 1
}

if (require.main === module) {
  main()
    .catch((err) => {
      process.stderr.write(`atlas:import failed: ${err.message}\n`)
      process.exitCode = 1
    })
    .finally(() => db().close())
}

module.exports = { describe, parseArgs }
