/**
 * GSO Error Reporter & Analytics (GDD Phase 3 — v3.2 lightweight implementation)
 * Logs structured errors to file + provides in-memory analytics counters.
 * Can be wired to external services (Sentry, Datadog) by replacing _sendToExternal().
 */

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

class ErrorReporter {
  constructor(options = {}) {
    this.logDir    = options.logDir || path.join(__dirname, '../logs');
    this.service   = options.service || 'GameServer';
    this.env       = process.env.NODE_ENV || 'development';
    this.counters  = {};   // event_type → count
    this.errors    = [];   // last 100 errors in memory
    this.maxErrors = 100;

    // Ensure logs directory exists
    if (!fs.existsSync(this.logDir)) {
      fs.mkdirSync(this.logDir, { recursive: true });
    }
  }

  // ── Error capture ──────────────────────────────────────────────────────────
  captureError(err, context = {}) {
    const entry = {
      ts:       new Date().toISOString(),
      service:  this.service,
      env:      this.env,
      message:  err?.message || String(err),
      stack:    err?.stack || null,
      context,
    };

    // Store in memory ring buffer
    this.errors.push(entry);
    if (this.errors.length > this.maxErrors) this.errors.shift();

    // Write to daily log file (non-blocking)
    const logFile = path.join(this.logDir, `errors-${new Date().toISOString().slice(0,10)}.log`);
    const line    = JSON.stringify(entry) + '\n';
    fs.appendFile(logFile, line, () => {}); // fire-and-forget

    // Increment counter
    this.increment('errors.total');

    // Hook for external service (Sentry, etc.)
    this._sendToExternal(entry);

    return entry;
  }

  // ── Analytics event tracking ───────────────────────────────────────────────
  track(event, data = {}) {
    this.increment(event);
    if (this.env === 'development') {
      const logFile = path.join(this.logDir, `analytics-${new Date().toISOString().slice(0,10)}.log`);
      fs.appendFile(logFile, JSON.stringify({ ts: new Date().toISOString(), event, data }) + '\n', () => {});
    }
  }

  increment(key) {
    this.counters[key] = (this.counters[key] || 0) + 1;
  }

  // ── Metrics snapshot ───────────────────────────────────────────────────────
  getMetrics() {
    return {
      service:   this.service,
      uptime:    Math.round(process.uptime()),
      memoryMB:  Math.round(process.memoryUsage().heapUsed / 1048576),
      counters:  { ...this.counters },
      recentErrors: this.errors.slice(-10).map(e => ({ ts: e.ts, message: e.message, context: e.context })),
    };
  }

  // ── Express middleware ─────────────────────────────────────────────────────
  requestMiddleware() {
    return (req, res, next) => {
      const start = Date.now();
      this.increment('http.requests');
      res.on('finish', () => {
        const ms = Date.now() - start;
        this.increment(`http.${res.statusCode >= 400 ? 'errors' : 'success'}`);
        if (ms > 2000) this.track('http.slow_request', { path: req.path, ms });
      });
      next();
    };
  }

  errorMiddleware() {
    return (err, req, res, next) => {
      this.captureError(err, { path: req.path, method: req.method });
      res.status(500).json({ error: 'Internal server error' });
    };
  }

  // ── Socket.IO event tracking helper ───────────────────────────────────────
  trackSocketEvent(eventName, userId) {
    this.increment(`socket.${eventName}`);
    this.increment('socket.total');
  }

  // ── External service stub ──────────────────────────────────────────────────
  _sendToExternal(entry) {
    // Replace with: Sentry.captureException(new Error(entry.message))
    // or: axios.post(process.env.ERROR_WEBHOOK_URL, entry)
    // Currently: no-op in development; log to console in production
    if (this.env === 'production') {
      console.error('[ErrorReporter]', entry.message, entry.context);
    }
  }
}

// Singleton
const reporter = new ErrorReporter({ service: 'GameServer' });

module.exports = reporter;
