'use strict';

/**
 * Unit tests for config.js
 */

const { describe, it, beforeEach, afterEach } = require('node:test');
const assert = require('node:assert/strict');

const { buildConfig, resetConfig } = require('../../src/config');

describe('config.js', () => {
  const originalEnv = {};

  beforeEach(() => {
    // Save and clear relevant env vars
    const keys = [
      'MM_BOT_TOKEN',
      'MM_BASE_URL',
      'MM_MAX_SOCKETS',
      'TRANSCRIPT_DIR',
      'THROTTLE_MS',
      'IDLE_TIMEOUT_S',
      'SESSION_POLL_MS',
      'MAX_ACTIVE_SESSIONS',
      'MAX_MESSAGE_CHARS',
      'MAX_STATUS_LINES',
      'MAX_RETRIES',
      'CIRCUIT_BREAKER_THRESHOLD',
      'CIRCUIT_BREAKER_COOLDOWN_S',
      'HEALTH_PORT',
      'LOG_LEVEL',
      'PID_FILE',
      'OFFSET_FILE',
      'TOOL_LABELS_FILE',
      'DEFAULT_CHANNEL',
      'ENABLE_FS_WATCH',
      'MM_PORT',
    ];
    for (const k of keys) {
      originalEnv[k] = process.env[k];
      delete process.env[k];
    }
    resetConfig();
  });

  afterEach(() => {
    // Restore env
    for (const [k, v] of Object.entries(originalEnv)) {
      if (v === undefined) delete process.env[k];
      else process.env[k] = v;
    }
    resetConfig();
  });

  it('throws if MM_BOT_TOKEN is missing', () => {
    assert.throws(() => buildConfig(), /MM_BOT_TOKEN/);
  });

  it('builds config with only required vars', () => {
    process.env.MM_BOT_TOKEN = 'test-token';
    const cfg = buildConfig();
    assert.equal(cfg.mm.token, 'test-token');
    assert.equal(cfg.mm.baseUrl, 'https://slack.solio.tech');
    assert.equal(cfg.throttleMs, 500);
    assert.equal(cfg.idleTimeoutS, 60);
    assert.equal(cfg.maxActiveSessions, 20);
    assert.equal(cfg.healthPort, 9090);
    assert.equal(cfg.logLevel, 'info');
  });

  it('reads all env vars correctly', () => {
    process.env.MM_BOT_TOKEN = 'mytoken';
    process.env.MM_BASE_URL = 'https://mm.example.com';
    process.env.MM_MAX_SOCKETS = '8';
    process.env.THROTTLE_MS = '250';
    process.env.IDLE_TIMEOUT_S = '120';
    process.env.MAX_ACTIVE_SESSIONS = '10';
    process.env.MAX_MESSAGE_CHARS = '5000';
    process.env.LOG_LEVEL = 'debug';
    process.env.HEALTH_PORT = '8080';
    process.env.ENABLE_FS_WATCH = 'false';

    const cfg = buildConfig();
    assert.equal(cfg.mm.token, 'mytoken');
    assert.equal(cfg.mm.baseUrl, 'https://mm.example.com');
    assert.equal(cfg.mm.maxSockets, 8);
    assert.equal(cfg.throttleMs, 250);
    assert.equal(cfg.idleTimeoutS, 120);
    assert.equal(cfg.maxActiveSessions, 10);
    assert.equal(cfg.maxMessageChars, 5000);
    assert.equal(cfg.logLevel, 'debug');
    assert.equal(cfg.healthPort, 8080);
    assert.equal(cfg.enableFsWatch, false);
  });

  it('throws on invalid MM_BASE_URL', () => {
    process.env.MM_BOT_TOKEN = 'token';
    process.env.MM_BASE_URL = 'not-a-url';
    assert.throws(() => buildConfig(), /MM_BASE_URL/);
  });

  it('throws on non-integer THROTTLE_MS', () => {
    process.env.MM_BOT_TOKEN = 'token';
    process.env.THROTTLE_MS = 'abc';
    assert.throws(() => buildConfig(), /THROTTLE_MS/);
  });

  it('ENABLE_FS_WATCH accepts "1", "true", "yes"', () => {
    process.env.MM_BOT_TOKEN = 'token';

    process.env.ENABLE_FS_WATCH = '1';
    assert.equal(buildConfig().enableFsWatch, true);
    resetConfig();

    process.env.ENABLE_FS_WATCH = 'true';
    assert.equal(buildConfig().enableFsWatch, true);
    resetConfig();

    process.env.ENABLE_FS_WATCH = 'yes';
    assert.equal(buildConfig().enableFsWatch, true);
    resetConfig();

    process.env.ENABLE_FS_WATCH = '0';
    assert.equal(buildConfig().enableFsWatch, false);
    resetConfig();
  });

  it('nullish defaults for optional string fields', () => {
    process.env.MM_BOT_TOKEN = 'token';
    const cfg = buildConfig();
    assert.equal(cfg.toolLabelsFile, null);
    assert.equal(cfg.defaultChannel, null);
  });
});
