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

vi.mock('./logger.js', () => ({
  logger: {
    debug: vi.fn(),
    info: vi.fn(),
    warn: vi.fn(),
    error: vi.fn(),
  },
}));

import {
  activeTenantRuntimeProcs,
  shutdownActiveTenantRuntimeProcs,
} from './tenant-nerdctl.js';

describe('tenant runtime shutdown', () => {
  beforeEach(() => {
    vi.useFakeTimers();
    activeTenantRuntimeProcs.clear();
  });

  afterEach(() => {
    vi.restoreAllMocks();
    vi.useRealTimers();
    activeTenantRuntimeProcs.clear();
  });

  it('skips SIGKILL when detached runtime helpers exit after SIGTERM', async () => {
    activeTenantRuntimeProcs.set(4101, {} as any);
    const killSpy = vi
      .spyOn(process, 'kill')
      .mockImplementation(() => true as never);

    const shutdownPromise = shutdownActiveTenantRuntimeProcs(1000);
    await vi.advanceTimersByTimeAsync(300);
    activeTenantRuntimeProcs.delete(4101);
    await vi.advanceTimersByTimeAsync(1000);
    await shutdownPromise;

    expect(killSpy).toHaveBeenCalledWith(-4101, 'SIGTERM');
    expect(killSpy).not.toHaveBeenCalledWith(-4101, 'SIGKILL');
  });

  it('escalates lingering detached runtime helpers to SIGKILL', async () => {
    activeTenantRuntimeProcs.set(4102, {} as any);
    const killSpy = vi
      .spyOn(process, 'kill')
      .mockImplementation(() => true as never);

    const shutdownPromise = shutdownActiveTenantRuntimeProcs(1000);
    await vi.advanceTimersByTimeAsync(1000);
    await shutdownPromise;

    expect(killSpy).toHaveBeenCalledWith(-4102, 'SIGTERM');
    expect(killSpy).toHaveBeenCalledWith(-4102, 'SIGKILL');
  });
});
