// messageCreate orchestration: allowlist bypass -> invite link -> banned word
// -> spam/mass-mention/mass-emoji. Invite/spam triggers always delete + warn
// (no severity tiers for those, unlike the word filter) — kept simple per the
// spec's "start simple" guidance. Filter-triggered mutes use a fixed 10-minute
// duration; per-severity-configurable durations are a future refinement.
const filterCache = require('../filter/filterCache')
const { findMatch } = require('../filter/normalize')
const inviteFilter = require('../filter/inviteFilter')
const spamFilter = require('../filter/spamFilter')
const warnings = require('../model/warnings')
const modLog = require('./modLog')
const createLogger = require('../utils/logger')

const log = createLogger('filter')

const FILTER_MUTE_SECONDS = 600 // 10 minutes

function botActor(client) {
  return { id: client.user.id, tag: client.user.tag }
}

async function isBypassed(message, cache) {
  if (cache.allowChannels.has(message.channelId)) return true
  const memberRoles = message.member ? message.member.roles.cache : null
  if (memberRoles && [...memberRoles.keys()].some((id) => cache.allowRoles.has(id))) return true
  return false
}

async function applyWarnAction(message, reason) {
  const staff = botActor(message.client)
  await warnings.add({
    guildId: message.guildId,
    targetUserId: message.author.id,
    targetTag: message.author.tag,
    staffUserId: staff.id,
    staffTag: staff.tag,
    reason,
  })
  await modLog.record({ client: message.client, guildId: message.guildId, actionType: 'warn', target: message.author, staffUser: staff, reason })
}

async function applyMuteAction(message, reason) {
  const staff = botActor(message.client)
  if (message.member && message.member.moderatable) {
    await message.member.timeout(FILTER_MUTE_SECONDS * 1000, reason)
  }
  await modLog.record({
    client: message.client,
    guildId: message.guildId,
    actionType: 'mute',
    target: message.author,
    staffUser: staff,
    reason,
    durationSeconds: FILTER_MUTE_SECONDS,
  })
}

async function handleMessageCreate(message) {
  if (message.author.bot || !message.guildId) return

  try {
    const cache = await filterCache.getOrLoad(message.guildId)
    if (await isBypassed(message, cache)) return

    if (await inviteFilter.containsForeignInvite(message)) {
      await message.delete().catch(() => {})
      await applyWarnAction(message, 'Posted a Discord invite link')
      return
    }

    const match = findMatch(message.content, cache.words)
    if (match) {
      await message.delete().catch(() => {})
      if (match.severity === 'mute') await applyMuteAction(message, `Filtered word: ${match.word}`)
      else if (match.severity === 'warn') await applyWarnAction(message, `Filtered word: ${match.word}`)
      return
    }

    if (
      spamFilter.isRateLimited(message.guildId, message.author.id) ||
      spamFilter.isMassMention(message) ||
      spamFilter.isMassEmoji(message.content)
    ) {
      await message.delete().catch(() => {})
      await applyWarnAction(message, 'Automated spam detection (rate limit / mass mention / mass emoji)')
    }
  } catch (err) {
    log.error('messageFilter failed', { message: err.message })
  }
}

module.exports = { handleMessageCreate }
