// ide-extension-discovery.test.mjs — discoverJetBrainsExtensions integration tests.
// All fixtures built in-test via mkdtemp + mkdir — no committed filesystem state.

import { describe, it, after } from 'node:test';
import assert from 'node:assert/strict';
import { mkdtemp, mkdir, rm } from 'node:fs/promises';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import {
  discoverJetBrainsExtensions,
  getAndroidStudioBaseDir,
} from '../../scanners/lib/ide-extension-discovery.mjs';

const TEST_PREFIX = 'llmsec-jbdisc-';
const created = [];

async function buildFixtureBase(layout) {
  const base = await mkdtemp(join(tmpdir(), TEST_PREFIX));
  created.push(base);
  for (const [product, plugins] of Object.entries(layout)) {
    for (const plug of plugins) {
      await mkdir(join(base, product, 'plugins', plug), { recursive: true });
    }
  }
  return base;
}

describe('discoverJetBrainsExtensions — basic walk', () => {
  it('finds plugins under IntelliJIdea<version>/plugins/', async () => {
    const base = await buildFixtureBase({
      'IntelliJIdea2024.3': ['com.example.one', 'com.example.two'],
    });
    const res = await discoverJetBrainsExtensions({ rootsOverride: [base] });
    assert.equal(res.extensions.length, 2);
    assert.ok(res.extensions.every(e => e.type === 'jetbrains'));
    assert.ok(res.extensions.some(e => e.name === 'com.example.one'));
    assert.equal(res.extensions[0].productDir, 'IntelliJIdea2024.3');
  });
});

describe('discoverJetBrainsExtensions — Fleet excluded', () => {
  it('ignores Fleet directory', async () => {
    const base = await buildFixtureBase({
      'IntelliJIdea2024.3': ['com.example.good'],
      'Fleet': ['com.example.fleet'],
    });
    const res = await discoverJetBrainsExtensions({ rootsOverride: [base] });
    assert.equal(res.extensions.length, 1);
    assert.equal(res.extensions[0].name, 'com.example.good');
    assert.ok(res.extensions.every(e => !e.location.includes('Fleet')));
  });
});

describe('discoverJetBrainsExtensions — Android Studio support', () => {
  it('discovers from AndroidStudio product dir', async () => {
    const base = await buildFixtureBase({
      'AndroidStudio2024.3.1': ['com.google.example'],
    });
    const res = await discoverJetBrainsExtensions({ rootsOverride: [base] });
    assert.equal(res.extensions.length, 1);
    assert.equal(res.extensions[0].productDir, 'AndroidStudio2024.3.1');
  });
});

describe('discoverJetBrainsExtensions — multi-product', () => {
  it('walks all matching product dirs', async () => {
    const base = await buildFixtureBase({
      'IntelliJIdea2024.3': ['a'],
      'PyCharm2024.3': ['b'],
      'GoLand2024.3': ['c'],
      'Toolbox': ['d'], // excluded
    });
    const res = await discoverJetBrainsExtensions({ rootsOverride: [base] });
    assert.equal(res.extensions.length, 3);
    assert.ok(!res.extensions.some(e => e.location.includes('Toolbox')));
  });
});

describe('discoverJetBrainsExtensions — skip hidden + disabled_plugins.txt', () => {
  it('ignores dotfile plugins and disabled_plugins.txt', async () => {
    const base = await buildFixtureBase({
      'IntelliJIdea2024.3': ['.hidden', 'com.real', 'disabled_plugins.txt'],
    });
    const res = await discoverJetBrainsExtensions({ rootsOverride: [base] });
    assert.equal(res.extensions.length, 1);
    assert.equal(res.extensions[0].name, 'com.real');
  });
});

describe('getAndroidStudioBaseDir — Linux path divergence', () => {
  it('is a path-producing function (no exception)', () => {
    // Actual return value is null or a path depending on host — just assert no throw.
    const v = getAndroidStudioBaseDir();
    assert.ok(v === null || typeof v === 'string');
  });
});

after(async () => {
  for (const r of created) await rm(r, { recursive: true, force: true }).catch(() => {});
});
