'use strict'

/**
 * follow-up-detector.js — detecta quando o cliente está cobrando uma resposta
 *                         que ele acha que ficou sem retorno.
 *
 * Padrões típicos no WhatsApp:
 *   - "?????"  / "???"   / "??"        — apenas pontuação
 *   - "verificou?"     "verificou??"
 *   - "viu?"           "olá??"
 *   - "alô??"          "ei??"
 *   - "tá aí?"         "alguém aí?"
 *   - "e aí?"          "e então?"
 *   - "?"              (interrogação isolada)
 *   - mensagens curtas (<= 2 palavras) terminando com ?
 *
 * Quando detecta, recupera a última pergunta do cliente que ficou sem resposta
 * e devolve um payload enriquecido para a IA: "[Cliente está cobrando a resposta
 * de uma pergunta anterior — pergunta original: 'X']".
 *
 * Bypassa cooldown — cliente impaciente precisa de feedback rápido (mesmo que
 * seja só uma mensagem-segura "estamos verificando, um momento").
 */

const { query, queryOne } = require('../../database/postgres')

// ── Detecção de padrão ────────────────────────────────────────────────────────

const PING_PATTERNS = [
  /^\s*\?{1,}\s*$/,                                 // só "?", "??", "?????"
  /^\s*\.{2,}\s*$/,                                 // "..", "..." (cobrança silenciosa)
  /^\s*(verificou|viu|olha|al[ôo]|ei|oi|ol[áa])\s*\?+\s*$/i,
  /^\s*(t[áa]|est[áa])\s+a[íi]\s*\?+\s*$/i,
  /^\s*(algu[ée]m|tem\s+algu[ée]m)\s+a[íi]\s*\?+\s*$/i,
  /^\s*e?\s*(a[íi]|ent[ãa]o|n[ãa]o)\s*\?+\s*$/i,
  /^\s*(j[áa]\s+)?(viu|verificou|conferiu|olhou)\s*\?+\s*$/i,
  /^\s*(consegue|conseguiu|deu|teve)\s+(ver|olhar|verificar)\s*\?+\s*$/i,
  /^\s*(pra|para)?\s*hoje\s*\?+\s*$/i,
  /^\s*responde\s+a[íi]\s*\??\s*$/i,
  /^\s*me\s+responde\s*\??\s*$/i,
]

/**
 * Retorna true se a mensagem parece uma cobrança/ping de follow-up.
 * @param {string} body — texto da mensagem
 */
function isFollowUpPing(body) {
  if (!body) return false
  const t = body.trim()
  // Mensagens longas (>40 chars) raramente são pings
  if (t.length > 40) return false
  for (const re of PING_PATTERNS) {
    if (re.test(t)) return true
  }
  return false
}

// ── Lookup da pergunta anterior sem resposta ──────────────────────────────────

/**
 * Busca a última pergunta do cliente neste chat que ainda não foi respondida.
 * "Não respondida" = não há mensagem fromMe=true ou auto_reply com status='sent*'
 * APÓS aquela mensagem do cliente.
 *
 * @param {string} chatId
 * @param {number} lookbackMinutes — janela máxima para buscar (default 24h)
 * @returns {Promise<{ body: string, ageMinutes: number } | null>}
 */
async function findPendingQuestion(chatId, lookbackMinutes = 1440) {
  if (!chatId) return null

  // Pega últimos eventos do chat na janela
  const events = await query(
    `SELECT direction, from_me, msg_type, payload, created_at
     FROM nw_event_logs
     WHERE chat_id = $1
       AND event = 'message.new'
       AND created_at > NOW() - ($2 || ' minutes')::interval
     ORDER BY created_at DESC
     LIMIT 50`,
    [chatId, String(lookbackMinutes)],
  ).catch(() => [])

  if (!events.length) return null

  // events[0] é o ping ATUAL (mais recente). É o limite superior do intervalo
  // de busca: queremos saber se a pergunta original foi respondida ENTRE
  // o momento em que ela foi feita E o momento do ping atual.
  const currentPingTime = events[0].created_at

  // Procura, do mais recente para o mais antigo (pulando o próprio ping):
  //   - Última msg do cliente (from_me=false) que NÃO seja outro ping
  //   - Se houver fromMe=true entre ela e o ping atual → já foi respondida
  let foundClientMsg = null
  let hasOperatorBetween = false

  for (let i = 1; i < events.length; i++) {  // i=1 pula o ping atual
    const ev = events[i]
    const body = ev.payload?.body ?? ''

    if (ev.from_me) {
      // Resposta do operador/bot (entre alguma msg antiga do cliente e o ping atual)
      hasOperatorBetween = true
      continue
    }

    // Mensagem do cliente — pula pings sucessivos ("?", "??", "alô?")
    if (!body || !body.trim() || isFollowUpPing(body)) continue

    // Achou pergunta substantiva. Se houve operador entre ela e o ping → respondida.
    if (hasOperatorBetween) return null
    foundClientMsg = ev
    break
  }

  if (!foundClientMsg) return null

  // Confirma checando nw_auto_replies — bot pode ter respondido sem aparecer
  // como event from_me=true (depende do echo da motor). Janela: estritamente
  // entre o momento da pergunta e o momento do ping atual (exclusivo).
  //
  // EXCLUI auto_replies cujo `user_msg` foi um ping ou um body enriquecido
  // de ping anterior — essas respostas NÃO contam como ter "respondido a
  // pergunta original", já que foram só reações a cobranças genéricas.
  const repliesBetween = await query(
    `SELECT user_msg FROM nw_auto_replies
     WHERE chat_id = $1
       AND created_at > $2
       AND created_at < $3
       AND status IN ('sent','sent_local')
     ORDER BY created_at`,
    [chatId, foundClientMsg.created_at, currentPingTime],
  ).catch(() => [])

  const isPingReply = (userMsg) => {
    if (!userMsg) return true
    const t = userMsg.trim()
    // Body enriquecido por buildEnrichedBody começa com '[O cliente enviou apenas' ou '[Atenção: o cliente está cobrando'
    if (/^\[(O cliente enviou apenas|Atenção: o cliente está cobrando)/i.test(t)) return true
    return isFollowUpPing(t)
  }

  const hasRealReply = repliesBetween.some(r => !isPingReply(r.user_msg))
  if (hasRealReply) return null  // já foi respondida com conteúdo real

  const ageMs = Date.now() - new Date(foundClientMsg.created_at).getTime()
  return {
    body: (foundClientMsg.payload?.body ?? '').trim(),
    ageMinutes: Math.round(ageMs / 60000),
  }
}

/**
 * Compõe a mensagem que será enviada ao LLM, dando contexto ao ping.
 * Se há pergunta pendente: instrui a IA a responder ela.
 * Se não há (ping aleatório, sem histórico): saudação simples.
 */
function buildEnrichedBody(pingBody, pending) {
  if (pending) {
    return (
      `[Atenção: o cliente está cobrando uma resposta. Há ${pending.ageMinutes}min ele perguntou:\n` +
      `"${pending.body}"\n` +
      `Agora ele reenviou apenas "${pingBody}" para chamar atenção. ` +
      `Responda à pergunta original o mais diretamente possível. ` +
      `Se realmente não souber a resposta ou se for assunto que precisa de operador humano, ` +
      `peça desculpa pela demora e diga que vai chamar um atendente.]`
    )
  }
  // Sem pergunta pendente — saudação leve
  return (
    `[O cliente enviou apenas "${pingBody}" sem contexto anterior nas últimas 2h. ` +
    `Responda com uma saudação curta perguntando como pode ajudar.]`
  )
}

module.exports = { isFollowUpPing, findPendingQuestion, buildEnrichedBody }
