'use strict';

const crypto = require('crypto');
const fs = require('fs');
const path = require('path');

const WAL_MAX_SIZE = 10 * 1024 * 1024;
const WAL_REDACT_KEYS = new Set(['content', 'text', 'body', 'message', 'answer']);

function createWriteAuditLog({ dataDir, maxSize = WAL_MAX_SIZE, redactKeys = WAL_REDACT_KEYS }) {
  let walStream = null;

  function getWalPath() {
    return path.join(process.env.WALL_E_DATA_DIR || dataDir, 'brain-wal.jsonl');
  }

  function redactValue(key, value) {
    if (!value || typeof value !== 'string') return value;
    if (redactKeys.has(key)) {
      return `[redacted:${crypto.createHash('sha256').update(value).digest('hex').slice(0, 12)}]`;
    }
    return value;
  }

  function logWrite(operation, table, data) {
    try {
      const walPath = getWalPath();
      try {
        const stat = fs.statSync(walPath);
        if (stat.size > maxSize) {
          if (walStream) {
            walStream.end();
            walStream = null;
          }
          fs.renameSync(walPath, walPath.replace('.jsonl', `.${Date.now()}.jsonl`));
        }
      } catch (e) {
        if (e && e.code !== 'ENOENT') {
          console.error('[write-audit] rotation failed:', e.message);
        }
      }

      if (!walStream) {
        walStream = fs.createWriteStream(walPath, { flags: 'a' });
        // If the stream errors mid-write (e.g. fs full, FD revoked), drop the
        // reference so the next call reopens. Without this, all subsequent
        // writes silently fail against a permanently-broken stream.
        walStream.on('error', (err) => {
          console.error('[write-audit] stream error:', err.message);
          walStream = null;
        });
      }

      const meta = {};
      for (const [k, v] of Object.entries(data || {})) {
        if (k !== 'id') meta[k] = redactValue(k, v);
      }

      walStream.write(JSON.stringify({
        ts: new Date().toISOString(),
        op: operation,
        table,
        id: data.id || null,
        meta,
      }) + '\n');
    } catch (e) {
      console.error('[write-audit] logWrite failed:', e.message);
    }
  }

  function close() {
    if (walStream) {
      walStream.end();
      walStream = null;
    }
  }

  return { close, logWrite };
}

module.exports = { WAL_MAX_SIZE, WAL_REDACT_KEYS, createWriteAuditLog };
