/**
 * Nesting-guard tests — DC-077 (data/data recursive duplicate cleanup)
 *
 * The guard runs at app startup. Pre-fix, `src/config/paths.js` did NOT
 * re-export `dataDir`, so `paths.dataDir` resolved to `undefined`. The
 * outer try/catch swallowed the resulting `TypeError [ERR_INVALID_ARG_TYPE]`
 * and the entire guard became a silent no-op — every startup logged
 * `[nesting-guard] Skipped: The "path" argument must be of type string.
 * Received undefined`. Post-fix, paths.js exports `dataDir` and the guard
 * falls back to platform-paths directly if `paths.dataDir` is missing.
 *
 * Tests use jest.isolateModules() for clean module-cache isolation.
 * jest.doMock is intentionally avoided — it persists across tests in a
 * describe and is the root cause of subtle flakes.
 */

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

describe('nesting-guard (DC-077)', () => {
  const originalEnv = { ...process.env };

  beforeEach(() => {
    jest.restoreAllMocks();
  });

  afterEach(() => {
    process.env = { ...originalEnv };
    jest.restoreAllMocks();
  });

  function makeTmpTree() {
    return fs.mkdtempSync(path.join(os.tmpdir(), 'nest-guard-'));
  }

  function writeJson(p, obj) {
    fs.mkdirSync(path.dirname(p), { recursive: true });
    fs.writeFileSync(p, JSON.stringify(obj));
  }

  it('removes a recursive data/data duplicate when present', () => {
    const tmp = makeTmpTree();
    writeJson(path.join(tmp, 'config.json'), { x: 1 });
    writeJson(path.join(tmp, 'data', 'config.json'), { x: 1 });
    writeJson(path.join(tmp, 'data', 'services.json'), []);

    process.env.SERVICES_FILE = path.join(tmp, 'services.json');
    process.env.CONFIG_FILE = path.join(tmp, 'config.json');

    let cleanupLog = '';
    let warnLog = '';
    jest.isolateModules(() => {
      const guard = require('../src/utilities/nesting-guard');
      jest.spyOn(console, 'log').mockImplementation((m) => { cleanupLog += String(m) + '\n'; });
      jest.spyOn(console, 'warn').mockImplementation((m) => { warnLog += String(m) + '\n'; });
      guard();
    });

    expect(fs.existsSync(path.join(tmp, 'data'))).toBe(false);
    expect(fs.existsSync(path.join(tmp, 'config.json'))).toBe(true);
    expect(cleanupLog).toMatch(/Removing recursive data nesting|Recursive nesting removed/);
    expect(warnLog).not.toMatch(/Skipped/);
  });

  it('does nothing when no nested data/data directory exists', () => {
    const tmp = makeTmpTree();
    writeJson(path.join(tmp, 'config.json'), { x: 1 });

    process.env.SERVICES_FILE = path.join(tmp, 'services.json');
    process.env.CONFIG_FILE = path.join(tmp, 'config.json');

    let cleanupLog = '';
    let warnLog = '';
    jest.isolateModules(() => {
      const guard = require('../src/utilities/nesting-guard');
      jest.spyOn(console, 'log').mockImplementation((m) => { cleanupLog += String(m) + '\n'; });
      jest.spyOn(console, 'warn').mockImplementation((m) => { warnLog += String(m) + '\n'; });
      guard();
    });

    expect(fs.existsSync(path.join(tmp, 'config.json'))).toBe(true);
    expect(warnLog).not.toMatch(/Skipped/);
    expect(cleanupLog).not.toMatch(/Removing recursive data nesting/);
  });

  it('src/config/paths exports dataDir as a non-empty string', () => {
    let dataDir;
    jest.isolateModules(() => {
      const paths = require('../src/config/paths');
      dataDir = paths.dataDir;
    });
    expect(typeof dataDir).toBe('string');
    expect(dataDir.length).toBeGreaterThan(0);
  });

  it('src/config/paths.dataDir equals dirname(SERVICES_FILE) when SERVICES_FILE env is set', () => {
    const tmp = makeTmpTree();
    process.env.SERVICES_FILE = path.join(tmp, 'services.json');
    process.env.CONFIG_FILE = path.join(tmp, 'config.json');

    let servicesFile, dataDir;
    jest.isolateModules(() => {
      const paths = require('../src/config/paths');
      servicesFile = paths.SERVICES_FILE;
      dataDir = paths.dataDir;
    });

    expect(dataDir).toBe(path.dirname(servicesFile));
    expect(dataDir).toBe(tmp);
  });
});
