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

// homedir/platform are read at call time, so they can be stubbed per case.
vi.mock('node:os', async (importOriginal) => {
  const actual = await importOriginal<typeof import('node:os')>();
  return {
    ...actual,
    homedir: () => '/home/tester',
    platform: () => mockPlatform,
  };
});

let mockPlatform: NodeJS.Platform = 'linux';

const { getShellProfilePath, detectShell } = await import('../../src/platform/detect.js');

describe('getShellProfilePath', () => {
  const originalShell = process.env['SHELL'];
  const originalZdotdir = process.env['ZDOTDIR'];

  beforeEach(() => {
    mockPlatform = 'linux';
    delete process.env['ZDOTDIR'];
  });

  afterEach(() => {
    if (originalShell === undefined) delete process.env['SHELL'];
    else process.env['SHELL'] = originalShell;
    if (originalZdotdir === undefined) delete process.env['ZDOTDIR'];
    else process.env['ZDOTDIR'] = originalZdotdir;
  });

  // The regression this guards: setupPath() in stages/finalize.ts appends the
  // PATH export to whatever this returns. A line written to ~/.bashrc is
  // unreachable to `bash -lc`, systemd units and agent seats, because Debian's
  // default .bashrc returns early for non-interactive shells — so an install
  // reported success and left `mosaic: command not found`. Same for .zshrc,
  // which zsh only reads for interactive shells.
  it('never targets an interactive-only rc file', () => {
    for (const shell of ['/bin/bash', '/usr/bin/zsh']) {
      process.env['SHELL'] = shell;
      const profile = getShellProfilePath();
      expect(profile).not.toMatch(/\.bashrc$/);
      expect(profile).not.toMatch(/\.zshrc$/);
    }
  });

  it('uses ~/.profile for bash', () => {
    process.env['SHELL'] = '/bin/bash';
    expect(getShellProfilePath()).toBe('/home/tester/.profile');
  });

  it('uses ~/.zshenv for zsh', () => {
    process.env['SHELL'] = '/usr/bin/zsh';
    expect(getShellProfilePath()).toBe('/home/tester/.zshenv');
  });

  it('honours ZDOTDIR for zsh', () => {
    process.env['SHELL'] = '/usr/bin/zsh';
    process.env['ZDOTDIR'] = '/custom/zdot';
    expect(getShellProfilePath()).toBe('/custom/zdot/.zshenv');
  });

  it('falls back to ~/.profile for an unknown shell', () => {
    process.env['SHELL'] = '/bin/somethingelse';
    expect(detectShell()).toBe('unknown');
    expect(getShellProfilePath()).toBe('/home/tester/.profile');
  });

  it('still routes fish to its own config', () => {
    process.env['SHELL'] = '/usr/bin/fish';
    expect(getShellProfilePath()).toBe('/home/tester/.config/fish/config.fish');
  });
});
