/**
 * POST /api/comment
 * Soumettre un commentaire sur une fiche.
 *
 * Corps attendu :
 *   { orga_id: number, contenu: string, auteur_pseudo?: string, auteur_email?: string }
 *
 * Flux :
 *   1. Rate limit Redis : ≤ 5 commentaires / IP / jour (Sonnet 3)
 *   2. Validation basique
 *   3. Filtre éthique Mistral Nemo (timeout 2s — fallback pending si timeout/erreur)
 *   4. INSERT NocoDB table avis
 *   5. Retourner { ok: true, status: 'approved' | 'pending' }
 */

import { checkRateLimit } from '~/server/utils/rateLimit'

interface CommentBody {
  orga_id: number
  contenu: string
  auteur_pseudo?: string
  auteur_email?: string
}

interface MistralFilterResult {
  safe: boolean
  category: string | null
  reason: string | null
}

async function filtreEthique(
  contenu: string,
  mistralKey: string
): Promise<MistralFilterResult> {
  const controller = new AbortController()
  const timeout = setTimeout(() => controller.abort(), 2000)

  try {
    const response: any = await $fetch('https://api.mistral.ai/v1/chat/completions', {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${mistralKey}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        model: 'open-mistral-nemo',
        temperature: 0.0,
        max_tokens: 100,
        response_format: { type: 'json_object' },
        messages: [
          {
            role: 'system',
            content: `Tu es un modèle de modération de contenu. Tu analyses des commentaires soumis sur une plateforme professionnelle française dédiée aux architectes. Tu dois détecter les contenus problématiques.

CONTENUS À SIGNALER (safe=false) :
- Propos racistes, antisémites, islamophobes, xénophobes
- Propos sexistes, misogynes, homophobes, transphobes, LGBTQIA-phobes
- Propos validistes (mépris des personnes handicapées)
- Diffamation personnelle nominative (accusations graves sans fondement contre une personne identifiable)
- Spam publicitaire explicite (lien commercial non sollicité + texte promotionnel)
- Harcèlement ciblé, menaces explicites

CONTENUS À AUTORISER (safe=true) :
- Critiques d'organisations ou de services (même sévères), sans attaque personnelle
- Partages d'expériences professionnelles négatives factuelles
- Désaccords et débats professionnels
- Signalement d'erreurs ou d'informations inexactes

RÈGLES :
1. En cas de doute, favorise safe=true (la liberté d'expression professionnelle prime).
2. Le champ "category" est obligatoire si safe=false.
3. Le champ "reason" est une phrase courte en français (max 20 mots).
4. Retourne UNIQUEMENT un objet JSON valide.

FORMAT DE SORTIE :
{
  "safe": true | false,
  "category": "racisme" | "sexisme" | "homophobie" | "antisémitisme" | "lgbtqia-phobie" | "validisme" | "diffamation" | "spam" | "harcelement" | null,
  "reason": "string (max 20 mots)" | null
}`,
          },
          {
            role: 'user',
            content: `COMMENTAIRE À ANALYSER :\n\n"${contenu}"\n\nAnalyse ce commentaire et retourne le JSON de modération.`,
          },
        ],
      }),
      // @ts-ignore — signal pas dans les types $fetch mais fonctionne en pratique
      signal: controller.signal,
    })

    clearTimeout(timeout)
    const raw = response?.choices?.[0]?.message?.content ?? '{}'
    const parsed = JSON.parse(raw)
    return {
      safe: parsed.safe !== false,
      category: parsed.category ?? null,
      reason: parsed.reason ?? null,
    }
  } catch {
    clearTimeout(timeout)
    // Timeout ou erreur réseau → fallback pending
    return { safe: false, category: null, reason: 'timeout_ou_erreur_mistral' }
  }
}

export default defineEventHandler(async (event) => {
  const config = useRuntimeConfig()

  // Rate limit : 5 commentaires / IP / jour
  const ip =
    getHeader(event, 'x-forwarded-for')?.split(',')[0].trim() ||
    event.node.req.socket?.remoteAddress ||
    '0.0.0.0'

  const allowed = await checkRateLimit(ip, 'comment', 5)
  if (!allowed) {
    throw createError({
      statusCode: 429,
      statusMessage: 'Trop de commentaires. Réessaie demain.',
    })
  }

  const body = await readBody<CommentBody>(event)

  // Validation basique
  if (!body?.orga_id || !body?.contenu) {
    throw createError({ statusCode: 400, message: 'Champs requis manquants : orga_id, contenu' })
  }

  const contenu = body.contenu.trim()
  if (contenu.length < 10 || contenu.length > 500) {
    throw createError({ statusCode: 400, message: 'Le commentaire doit faire entre 10 et 500 caractères' })
  }

  // Filtre éthique Mistral Nemo
  let published = false
  let safeCheck = 'pending'
  let safeReason: string | null = null

  if (config.mistralApiKey) {
    const result = await filtreEthique(contenu, config.mistralApiKey)
    published = result.safe
    safeCheck = result.safe ? 'safe' : (result.reason === 'timeout_ou_erreur_mistral' ? 'pending' : 'flagged')
    safeReason = result.reason
  } else {
    // Clé Mistral absente → fallback pending (TODO configurer MISTRAL_API_KEY)
    safeCheck = 'pending'
    safeReason = 'mistral_key_manquante'
  }

  // Insertion NocoDB
  const tableId = config.commentTableId
  const url = `${config.nocodbUrl}/api/v2/tables/${tableId}/records`

  const record = await $fetch(url, {
    method: 'POST',
    headers: {
      'xc-token': config.nocodbToken,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      orga_id: body.orga_id,
      contenu,
      auteur_pseudo: body.auteur_pseudo || null,
      auteur_email: body.auteur_email || null,
      published,
      safe_check: safeCheck,
      safe_reason: safeReason,
      submitted_at: new Date().toISOString(),
    }),
  }).catch((err: any) => {
    throw createError({ statusCode: 502, message: 'Erreur NocoDB lors de l\'insertion du commentaire' })
  })

  return {
    ok: true,
    status: published ? 'approved' : 'pending',
    message: published
      ? 'Commentaire publié. Merci pour ta contribution !'
      : 'Commentaire reçu et en cours de modération.',
  }
})
