import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import * as path from 'path';

// vi.spyOn doesn't work on native ESM `os` exports (Module namespace is not
// configurable). vi.mock with a factory works because vitest hoists it and
// replaces the module record entirely. We control platform/homedir via the
// mocked factory and reset modules between tests so each test re-evaluates
// configure-mcp.ts with fresh module-level mocks.

const ORIG_ENV = { ...process.env };

let mockPlatform: NodeJS.Platform = 'linux';
let mockProcVersion: string | Error = 'Linux 6.5.0-generic';

vi.mock('os', async () => {
  const actual = await vi.importActual<typeof import('os')>('os');
  return {
    ...actual,
    platform: () => mockPlatform,
    homedir: () => '/home/testuser',
  };
});

vi.mock('fs', async () => {
  const actual = await vi.importActual<typeof import('fs')>('fs');
  return {
    ...actual,
    default: actual,
    readFileSync: (p: any, ...rest: any[]) => {
      if (typeof p === 'string' && p === '/proc/version') {
        if (mockProcVersion instanceof Error) throw mockProcVersion;
        return mockProcVersion;
      }
      return (actual.readFileSync as any)(p, ...rest);
    },
  };
});

describe('detectPlatform()', () => {
  beforeEach(() => {
    vi.resetModules();
    delete process.env.WSL_DISTRO_NAME;
    delete process.env.WSL_INTEROP;
    mockPlatform = 'linux';
    mockProcVersion = 'Linux 6.5.0-generic';
  });

  afterEach(() => {
    process.env = { ...ORIG_ENV };
  });

  it('returns "darwin" on macOS', async () => {
    mockPlatform = 'darwin';
    const { detectPlatform } = await import('../../scripts/configure-mcp');
    expect(detectPlatform()).toBe('darwin');
  });

  it('returns "win32" on native Windows', async () => {
    mockPlatform = 'win32';
    const { detectPlatform } = await import('../../scripts/configure-mcp');
    expect(detectPlatform()).toBe('win32');
  });

  it('returns "linux-wsl" when WSL_DISTRO_NAME is set', async () => {
    mockPlatform = 'linux';
    process.env.WSL_DISTRO_NAME = 'Ubuntu-22.04';
    const { detectPlatform } = await import('../../scripts/configure-mcp');
    expect(detectPlatform()).toBe('linux-wsl');
  });

  it('returns "linux-wsl" when /proc/version contains "microsoft"', async () => {
    mockPlatform = 'linux';
    mockProcVersion = 'Linux version 5.15.0-microsoft-standard-WSL2';
    const { detectPlatform } = await import('../../scripts/configure-mcp');
    expect(detectPlatform()).toBe('linux-wsl');
  });

  it('returns "linux" on plain Linux (no WSL markers)', async () => {
    mockPlatform = 'linux';
    mockProcVersion = 'Linux version 6.5.0-generic (buildd@lcy02-amd64)';
    const { detectPlatform } = await import('../../scripts/configure-mcp');
    expect(detectPlatform()).toBe('linux');
  });

  it('returns "linux" when /proc/version is missing', async () => {
    mockPlatform = 'linux';
    mockProcVersion = new Error('ENOENT');
    const { detectPlatform } = await import('../../scripts/configure-mcp');
    expect(detectPlatform()).toBe('linux');
  });
});

describe('isWindowsMountPath()', () => {
  it('flags /mnt/c/ paths', async () => {
    const { isWindowsMountPath } = await import('../../scripts/configure-mcp');
    expect(isWindowsMountPath('/mnt/c/Users/fried/priority-forge')).toBe(true);
    expect(isWindowsMountPath('/mnt/d/repos/priority-forge')).toBe(true);
    expect(isWindowsMountPath('/mnt/Z/repo')).toBe(true);
  });

  it('does not flag WSL home or normal Linux paths', async () => {
    const { isWindowsMountPath } = await import('../../scripts/configure-mcp');
    expect(isWindowsMountPath('/home/user/priority-forge')).toBe(false);
    expect(isWindowsMountPath('/root/repo')).toBe(false);
    expect(isWindowsMountPath('/Users/me/repo')).toBe(false);
    expect(isWindowsMountPath('/opt/priority-forge')).toBe(false);
  });

  it('does not flag non-mount /mnt paths', async () => {
    const { isWindowsMountPath } = await import('../../scripts/configure-mcp');
    expect(isWindowsMountPath('/mnt/data/repo')).toBe(false);
    expect(isWindowsMountPath('/mnt/backup/x')).toBe(false);
  });
});
