/**
 * POST /api/submit
 *
 * Soumission multi-type (ecosysteme / reseau / job / outil).
 * - Validation Zod côté serveur (champs communs + par type)
 * - Rate limit Redis : 3 soumissions / IP / jour
 * - Géocodage Nominatim (optionnel — fallback silencieux)
 * - INSERT NocoDB : moderation_status=pending, ai_processed=false
 *
 * Réponse 201 : { submissionId, message }
 * Réponse 422 : erreurs Zod
 * Réponse 429 : rate limit dépassé
 */

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

const SUBMISSION_TYPES = ['ecosysteme', 'reseau', 'job', 'outil'] as const

const FONCTIONS = [
  'Juridique', 'Technique', 'Économique', 'Administratif', 'Chantier',
  'Comptabilité', 'Développement', 'Formation', 'Gestion d\'agence', 'Santé mentale',
] as const

const ECHELLES = ['National', 'Régional', 'Local'] as const

const TERRITOIRES = [
  'Métropole', 'Guadeloupe', 'Martinique', 'Guyane', 'La Réunion', 'Mayotte',
] as const

const TYPES_PRINCIPAUX = ['agence', 'collectif', 'reseau', 'asso', 'ressource'] as const

const TYPES_PLATEFORME = ['mise-en-relation', 'appel-offre-public', 'communaute-pro'] as const

const CATEGORIES_OUTIL = ['simulateur', 'logiciel', 'guide', 'autre'] as const

export const SubmitSchema = z.object({
  // Champs communs
  nom: z.string().min(3, 'Minimum 3 caractères').max(150, 'Maximum 150 caractères').trim(),
  url: z.string().url('URL invalide').optional().or(z.literal('')).transform(v => v || undefined),
  description_user: z.string().min(50, 'Minimum 50 caractères').max(500, 'Maximum 500 caractères').trim(),
  submitted_by_email: z.string().email('Email invalide').optional().or(z.literal('')).transform(v => v || undefined),
  submission_type: z.enum(SUBMISSION_TYPES, { errorMap: () => ({ message: 'Type de soumission invalide' }) }),

  // Champs écosystème
  echelle: z.enum(ECHELLES).optional(),
  fonctions: z.array(z.enum(FONCTIONS)).min(1).max(5).optional(),
  territoire: z.enum(TERRITOIRES).optional(),
  localisation_ville: z.string().max(100).optional().transform(v => v?.trim() || undefined),

  // Champs réseau
  type_principal: z.enum(TYPES_PRINCIPAUX).optional(),
  projet_lien: z.string().url('URL invalide').optional().or(z.literal('')),
  projet_adresse: z.string().max(200).optional().transform(v => v?.trim() || undefined),

  // Champs job
  type_plateforme: z.enum(TYPES_PLATEFORME).optional(),

  // Champs outil
  categorie: z.enum(CATEGORIES_OUTIL).optional(),
})

export type SubmitInput = z.infer<typeof SubmitSchema>

// ── Géocodage Nominatim ───────────────────────────────────────────────────────

async function geocodeVille(
  ville: string,
): Promise<{ lat: number; lon: number } | null> {
  try {
    const url = `https://nominatim.openstreetmap.org/search?q=${encodeURIComponent(ville)}&format=json&limit=1&countrycodes=fr`
    const results: any[] = await $fetch(url, {
      headers: { 'User-Agent': 'NAV/2.0 contact@trans-former.fr' },
      timeout: 5000,
    })
    if (results.length > 0) {
      return { lat: parseFloat(results[0].lat), lon: parseFloat(results[0].lon) }
    }
  } catch {
    // Fallback silencieux — fiche stockée sans coordonnées
    console.warn('[submit] Géocodage Nominatim échoué pour :', ville)
  }
  return null
}

// ── Handler principal ─────────────────────────────────────────────────────────

export default defineEventHandler(async (event) => {
  // 1. Récupérer l'IP (proxy-aware)
  const ip =
    getHeader(event, 'x-forwarded-for')?.split(',')[0].trim() ||
    event.node.req.socket?.remoteAddress ||
    '0.0.0.0'

  // 2. Rate limit : 3 soumissions / IP / jour
  const allowed = await checkRateLimit(ip, 'submit', 3)
  if (!allowed) {
    throw createError({
      statusCode: 429,
      statusMessage: 'Trop de soumissions. Réessaie demain.',
    })
  }

  // 3. Lire et valider le body
  const body = await readBody(event)
  const parsed = SubmitSchema.safeParse(body)

  if (!parsed.success) {
    throw createError({
      statusCode: 422,
      statusMessage: 'Validation échouée',
      data: parsed.error.flatten().fieldErrors,
    })
  }

  const data = parsed.data

  // 4. Géocodage optionnel
  let latitude: number | null = null
  let longitude: number | null = null

  if (data.localisation_ville) {
    const coords = await geocodeVille(data.localisation_ville)
    if (coords) {
      latitude = coords.lat
      longitude = coords.lon
    }
  }

  // 5. INSERT NocoDB
  const config = useRuntimeConfig()
  const nocodbUrl = config.nocodbUrl
  const nocodbToken = config.nocodbToken
  const orgTableId = config.orgTableId
  const nocoBaseId = config.nocodbBase

  const payload: Record<string, unknown> = {
    submission_type: data.submission_type,
    nom: data.nom,
    url: data.url || null,
    description_user: data.description_user,
    submitted_by_email: data.submitted_by_email || null,
    moderation_status: 'pending',
    ai_processed: false,
    submitted_at: new Date().toISOString(),
    latitude,
    longitude,
  }

  // Champs spécifiques selon le type
  if (data.submission_type === 'ecosysteme') {
    payload.echelle = data.echelle
    payload.tags_fonction = data.fonctions?.join(',')
    payload.territoire = data.territoire
    payload.localisation_ville = data.localisation_ville || null
    payload.scrape_status = data.url ? 'pending' : 'no_link'
  } else if (data.submission_type === 'reseau') {
    payload.type_principal = data.type_principal
    payload.projet_lien = data.projet_lien || null
    payload.projet_adresse = data.projet_adresse || null
    payload.localisation_ville = data.localisation_ville || null
  } else if (data.submission_type === 'job') {
    payload.type_plateforme = data.type_plateforme
  } else if (data.submission_type === 'outil') {
    payload.categorie = data.categorie
  }

  // NocoDB v1 endpoint
  const insertUrl = `${nocodbUrl}/api/v1/db/data/noco/${nocoBaseId}/${orgTableId}`

  let insertedRecord: any
  try {
    insertedRecord = await $fetch(insertUrl, {
      method: 'POST',
      headers: {
        'xc-token': nocodbToken,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(payload),
    })
  } catch (e: any) {
    console.error('[submit] Erreur NocoDB insert:', e?.message ?? e)
    throw createError({
      statusCode: 502,
      statusMessage: 'Erreur serveur — réessaie dans quelques instants.',
    })
  }

  const submissionId = insertedRecord?.Id ?? insertedRecord?.id ?? null

  // 6. Notification email Jules (fire-and-forget — n'impacte pas la réponse)
  notifyJules(config, data, submissionId).catch((e) =>
    console.warn('[submit] Email notification échouée:', e?.message ?? e),
  )

  return {
    status: 201,
    submissionId,
    message: 'Ta fiche est en cours de traitement.',
    trackingUrl: submissionId
      ? `https://nav.trans-former.fr/suivi/${submissionId}`
      : null,
  }
})

async function notifyJules(
  config: ReturnType<typeof useRuntimeConfig>,
  data: SubmitInput,
  submissionId: number | null,
): Promise<void> {
  if (!config.resendApiKey) return

  const nocoAdminUrl = `http://localhost:8070`
  const body = {
    from: 'AEP Carte <contact@trans-former.fr>',
    to: [config.emailJules],
    subject: `[AEP] Nouvelle fiche soumise : ${data.nom}`,
    html: `
      <p><strong>Nouvelle fiche en attente de modération.</strong></p>
      <ul>
        <li><strong>Nom :</strong> ${data.nom}</li>
        <li><strong>URL :</strong> ${data.url ?? '—'}</li>
        <li><strong>Échelle :</strong> ${data.echelle}</li>
        <li><strong>Territoire :</strong> ${data.territoire}</li>
        <li><strong>Fonctions :</strong> ${data.fonctions.join(', ')}</li>
        <li><strong>Description :</strong> ${data.description_user}</li>
        ${data.submitted_by_email ? `<li><strong>Email soumetteur :</strong> ${data.submitted_by_email}</li>` : ''}
        ${submissionId ? `<li><strong>ID NocoDB :</strong> ${submissionId}</li>` : ''}
      </ul>
      <p><a href="${nocoAdminUrl}">Ouvrir NocoDB pour valider</a></p>
    `,
  }

  await $fetch('https://api.resend.com/emails', {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${config.resendApiKey}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(body),
  })
}
