// ── Admin · Cliloc table ───────────────────────────────────────────────────
//
// Operating the cliloc import: where the converted cliloc file is, whether it
// has drifted from what is loaded, and a forced reimport after a client patch
// (docs/website/CLILOCS.md).
//
// The policy lives in the model. This controller does three things and no more:
// it validates input, it maps a refresh RESULT onto an HTTP status, and it
// records the action in the admin activity log.
//
// **A refresh result is not an exception.** `shardClilocs.refresh()` reports
// `unavailable` / `failed` rather than throwing, because the boot path must never
// be stopped by a bad file. That contract is preserved here: a missing file, or
// the single most likely operator mistake — pointing at the client's own
// COMPRESSED `Cliloc.enu` — is a 200 carrying `status: 'unavailable'` and the
// reason, not a 500. A 500 would say only "something broke"; the operator needs
// to be told which file to convert.

const clilocs = require('../../../model/shardClilocs/shardClilocs.model')
const market = require('../../../model/shardMarket/shardMarket.model')
const activity = require('../../../model/activity/activity.model')

const log = require('../../../utils/logger')('admin-shard-clilocs')

// GET /admin/shard/clilocs — what is loaded, what the file looks like, whether
// they disagree. There is no public counterpart: the cliloc table is never
// served as a table, only applied to names the site already returns.
async function getStatus(req, res) {
  try {
    return res.json(await clilocs.status())
  } catch (err) {
    log.error('getStatus', err)
    return res.status(500).json({ message: 'Internal Server Error' })
  }
}

// POST /admin/shard/clilocs/import — reload after a client patch or a change to
// the shard's own overlay files, without a restart.
//
// `force` reimports even when the source hashes match what is loaded (the escape
// hatch for "the database is wrong but the files are not").
//
// `approve` accepts a refresh in which a previously-loaded source has VANISHED.
// That is refused by default because an unmounted volume and a deliberate
// deletion look identical from the server — the lighter cousin of the atlas's
// approve/reject flow, and the reason it can be a flag here rather than a
// pending table is that nothing is stored to approve: the import re-reads the
// files at approval time by construction.
async function importClilocs(req, res) {
  try {
    const force = !!req.body?.force
    const approve = !!req.body?.approve
    const result = await clilocs.refresh({ force, approve })

    // The marketplace denormalizes resolved item names into
    // shard_vendor_items.display_name, and the shard's market sweep will NOT
    // re-send an unchanged shop just because the site learned what its items are
    // called — so without this pass, an operator who imports clilocs after the
    // first sweep keeps seeing item ids until every shop happens to change.
    // Awaited (rather than fired and forgotten) so the panel's "imported" is
    // honest about the names being live; the pass is a bounded walk of one table
    // and never throws.
    if (result.status === 'imported') await market.refreshDisplayNames()

    await activity.log({
      req,
      action: 'shard.clilocs.import',
      detail: {
        force,
        approve,
        status: result.status,
        count: result.count ?? null,
        missingSources: result.missingSources ?? result.acceptedMissing ?? null,
      },
    })
    return res.json(result)
  } catch (err) {
    log.error('importClilocs', err)
    return res.status(500).json({ message: 'Internal Server Error' })
  }
}

// PUT /admin/shard/clilocs/path — point the site at a different cliloc file.
//
// Persisted as a setting, which wins over the UO_CLIENT_PATH env default so an
// operator can move the mount without a redeploy. Blank clears it, which turns
// resolution off (boot skips, the loaded table keeps serving) — a legitimate
// thing to want, so it is allowed rather than validated away.
//
// Deliberately does NOT import as a side effect, for the same reason the atlas
// path does not: changing where the table reads from and reloading it are
// separate decisions. The response carries the refreshed status so the panel can
// offer the import immediately.
async function setPath(req, res) {
  try {
    const value = String(req.body?.path ?? '').trim()
    await clilocs.setClientPath(value, req.user?.id ?? null)
    await activity.log({ req, action: 'shard.clilocs.path', detail: { path: value } })
    return res.json(await clilocs.status())
  } catch (err) {
    log.error('setClilocPath', err)
    return res.status(500).json({ message: 'Internal Server Error' })
  }
}

module.exports = { getStatus, importClilocs, setPath }
