const fs = require('fs');
const path = require('path');
const { v4: uuid } = require('uuid');

const CONFIG_DIR = path.join(__dirname, '..', 'config');
const LOG_FILE = path.join(CONFIG_DIR, 'request-logs.json');
const TTL_MS = 28 * 24 * 60 * 60 * 1000;
const MAX_BODY_CHARS = 10000;

function ensureDir() {
  if (!fs.existsSync(CONFIG_DIR)) {
    fs.mkdirSync(CONFIG_DIR, { recursive: true });
  }
}

function readLogs() {
  try {
    ensureDir();
    if (!fs.existsSync(LOG_FILE)) {
      return [];
    }
    const raw = fs.readFileSync(LOG_FILE, 'utf8');
    const parsed = JSON.parse(raw);
    return Array.isArray(parsed) ? parsed : [];
  } catch (error) {
    console.warn('[REQUEST-LOG] Konnte Logdatei nicht lesen:', error.message);
    return [];
  }
}

function persistLogs(logs) {
  try {
    ensureDir();
    fs.writeFileSync(LOG_FILE, JSON.stringify(logs, null, 2));
  } catch (error) {
    console.warn('[REQUEST-LOG] Konnte Logdatei nicht schreiben:', error.message);
  }
}

function prune(logs = []) {
  const cutoff = Date.now() - TTL_MS;
  return logs.filter((entry) => Number(entry?.timestamp) >= cutoff);
}

function serializeBodySnippet(body) {
  try {
    if (body === undefined || body === null) {
      return null;
    }
    let text = '';
    if (typeof body === 'string') {
      text = body;
    } else if (Buffer.isBuffer(body)) {
      text = body.toString('utf8');
    } else {
      text = JSON.stringify(body);
    }
    if (text.length > MAX_BODY_CHARS) {
      return `${text.slice(0, MAX_BODY_CHARS)}… (gekürzt)`;
    }
    return text;
  } catch (error) {
    return `<<Konnte Response nicht serialisieren: ${error.message}>>`;
  }
}

function add(entry = {}) {
  const logs = prune(readLogs());
  const record = {
    id: uuid(),
    timestamp: Date.now(),
    ...entry
  };
  if ('responseBody' in record) {
    record.responseBody = serializeBodySnippet(record.responseBody);
  }
  logs.push(record);
  persistLogs(logs);
  return record;
}

function list(limit) {
  const logs = prune(readLogs());
  persistLogs(logs);
  if (limit == null) {
    return logs.slice().reverse();
  }
  const sanitizedLimit = Math.max(1, Math.min(Number(limit) || 500, 10000));
  return logs.slice(-sanitizedLimit).reverse();
}

module.exports = {
  add,
  list,
  serializeBodySnippet
};
