/**
 * Rate limiting via fichiers JSON locaux
 * Implémentation recommandée spec F §8 : /tmp/nav-ratelimit/{IP_hash}.json
 *
 * - IP hashée SHA-256 (RGPD — pas de stockage IP en clair)
 * - Fichier JSON par IP, reset automatique si date != today
 * - Dossier créé au premier appel si absent
 *
 * Usage :
 *   const allowed = await checkRateLimitJson(ip, 'chatbot', 10)
 *   if (!allowed) throw createError({ statusCode: 429, ... })
 */

import { createHash } from 'crypto'
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs'
import { join } from 'path'

const RATELIMIT_DIR = '/tmp/nav-ratelimit'

type RateLimitFile = {
  [action: string]: { count: number; date: string }
}

function ensureDir() {
  if (!existsSync(RATELIMIT_DIR)) {
    mkdirSync(RATELIMIT_DIR, { recursive: true })
  }
}

function hashIp(ip: string): string {
  return createHash('sha256').update(ip).digest('hex')
}

function todayStr(): string {
  const d = new Date()
  return `${d.getUTCFullYear()}-${String(d.getUTCMonth() + 1).padStart(2, '0')}-${String(d.getUTCDate()).padStart(2, '0')}`
}

function readFile(ipHash: string): RateLimitFile {
  const path = join(RATELIMIT_DIR, `${ipHash}.json`)
  try {
    return JSON.parse(readFileSync(path, 'utf-8'))
  } catch {
    return {}
  }
}

function writeFile(ipHash: string, data: RateLimitFile) {
  const path = join(RATELIMIT_DIR, `${ipHash}.json`)
  writeFileSync(path, JSON.stringify(data), 'utf-8')
}

/**
 * Vérifie et incrémente le compteur pour une IP et une action.
 * @param ip        Adresse IP du client (sera hashée SHA-256)
 * @param action    Clé d'action (ex : 'chatbot', 'submit', 'comment')
 * @param maxPerDay Nombre max d'appels autorisés par jour
 * @returns true si autorisé, false si limite dépassée
 */
export function checkRateLimitJson(
  ip: string,
  action: string,
  maxPerDay: number,
): boolean {
  ensureDir()

  const ipHash = hashIp(ip)
  const today = todayStr()
  const data = readFile(ipHash)

  const entry = data[action]

  if (!entry || entry.date !== today) {
    // Nouveau jour ou premier appel : reset et autoriser
    data[action] = { count: 1, date: today }
    writeFile(ipHash, data)
    return true
  }

  if (entry.count >= maxPerDay) {
    return false
  }

  entry.count++
  writeFile(ipHash, data)
  return true
}
