// Admin moderation dashboard (Phase 6). Read-only views over the bot's
// mod_actions log plus server-owned staff notes. Mounted behind the
// admin+moderator RBAC gate (see admin.routes.js). The only mutation here is
// adding a staff note; admin_only notes are further restricted to the admin role.
const moderation = require('../../../model/moderation/moderation.model')
const modNotes = require('../../../model/modNotes/modNotes.model')
const modNotesDb = require('../../../model/modNotes/modNotes.db')
const activity = require('../../../model/activity/activity.model')

const log = require('../../../utils/logger')('moderation')

const VALID_TYPES = new Set(['ban', 'kick', 'mute', 'warn'])
const MAX_LIMIT = 200
const DEFAULT_LIMIT = 50

// Parse ?limit/&offset the same way the activity log does: numeric, capped.
function pageParams(req) {
  const limit = Math.min(Number(req.query.limit) || DEFAULT_LIMIT, MAX_LIMIT)
  const offset = Number(req.query.offset) || 0
  return { limit, offset }
}

// Optional ?type filter — ignored unless it is a known action type.
function typeParam(req) {
  const t = req.query.type
  return VALID_TYPES.has(t) ? t : null
}

function isAdmin(req) {
  return req.user && req.user.role === 'admin'
}

async function getSummary(req, res) {
  try {
    return res.json(await moderation.summary())
  } catch (err) {
    log.error('summary failed', { error: err.message })
    return res.status(500).json({ message: 'Internal Server Error' })
  }
}

async function getRecent(req, res) {
  try {
    const { limit, offset } = pageParams(req)
    return res.json(await moderation.recent({ type: typeParam(req), limit, offset }))
  } catch (err) {
    log.error('recent failed', { error: err.message })
    return res.status(500).json({ message: 'Internal Server Error' })
  }
}

async function search(req, res) {
  try {
    const term = (req.query.q || '').trim()
    if (!term) return res.json([])
    return res.json(await moderation.search(term, { limit: 20 }))
  } catch (err) {
    log.error('search failed', { error: err.message })
    return res.status(500).json({ message: 'Internal Server Error' })
  }
}

// ── Phase 6b event feeds ──────────────────────────────────────────────
const MEMBER_TYPES = new Set(['join', 'leave'])

async function getMembers(req, res) {
  try {
    const { limit, offset } = pageParams(req)
    const t = MEMBER_TYPES.has(req.query.type) ? req.query.type : null
    return res.json(await moderation.members({ type: t, limit, offset }))
  } catch (err) {
    log.error('members failed', { error: err.message })
    return res.status(500).json({ message: 'Internal Server Error' })
  }
}

async function getFilterHits(req, res) {
  try {
    const { limit, offset } = pageParams(req)
    return res.json(await moderation.filterHits({ limit, offset }))
  } catch (err) {
    log.error('filterHits failed', { error: err.message })
    return res.status(500).json({ message: 'Internal Server Error' })
  }
}

async function getSpamHits(req, res) {
  try {
    const { limit, offset } = pageParams(req)
    return res.json(await moderation.spamHits({ limit, offset }))
  } catch (err) {
    log.error('spamHits failed', { error: err.message })
    return res.status(500).json({ message: 'Internal Server Error' })
  }
}

async function getUser(req, res) {
  try {
    const summary = await moderation.userSummary(req.params.discordId)
    const notesCount = await modNotesDb.countForUser(req.params.discordId, {
      includeAdminOnly: isAdmin(req),
    })
    return res.json({ ...summary, notes_count: notesCount })
  } catch (err) {
    log.error('getUser failed', { error: err.message })
    return res.status(500).json({ message: 'Internal Server Error' })
  }
}

async function getUserActions(req, res) {
  try {
    const { limit, offset } = pageParams(req)
    return res.json(
      await moderation.userActions(req.params.discordId, { type: typeParam(req), limit, offset }),
    )
  } catch (err) {
    log.error('getUserActions failed', { error: err.message })
    return res.status(500).json({ message: 'Internal Server Error' })
  }
}

async function getUserNotes(req, res) {
  try {
    const notes = await modNotes.listForUser(req.params.discordId, {
      includeAdminOnly: isAdmin(req),
    })
    return res.json(notes)
  } catch (err) {
    log.error('getUserNotes failed', { error: err.message })
    return res.status(500).json({ message: 'Internal Server Error' })
  }
}

async function addUserNote(req, res) {
  try {
    const visibility = req.body.visibility === 'admin_only' ? 'admin_only' : 'staff_only'
    // admin_only notes can carry sensitive judgement calls — restrict to admins.
    if (visibility === 'admin_only' && !isAdmin(req)) {
      return res.status(403).json({ message: 'Only admins can add admin-only notes' })
    }
    const note = await modNotes.add({
      discordUserId: req.params.discordId,
      author: req.user,
      body: req.body.body,
      visibility,
    })
    await activity.log({
      req,
      action: 'moderation.note.add',
      detail: { discordUserId: req.params.discordId, visibility },
    })
    return res.status(201).json(note)
  } catch (err) {
    log.error('addUserNote failed', { error: err.message })
    return res.status(500).json({ message: 'Internal Server Error' })
  }
}

module.exports = {
  getSummary,
  getRecent,
  search,
  getMembers,
  getFilterHits,
  getSpamHits,
  getUser,
  getUserActions,
  getUserNotes,
  addUserNote,
}
