import { GpuCapabilityService } from './gpu-capability.service';

describe('GpuCapabilityService', () => {
  let service: GpuCapabilityService;
  const originalGpu = (navigator as unknown as { gpu: unknown }).gpu;

  function setGpu(value: unknown): void {
    Object.defineProperty(navigator, 'gpu', { value, configurable: true });
  }

  beforeEach(() => {
    service = new GpuCapabilityService();
  });

  afterEach(() => {
    setGpu(originalGpu);
  });

  it('reports "webgpu" when an adapter is available', async () => {
    setGpu({ requestAdapter: () => Promise.resolve({}) });

    const tier = await service.detect();

    expect(tier).toBe('webgpu');
    expect(service.tier()).toBe('webgpu');
  });

  it('falls back to "webgl" when WebGPU is missing but a WebGL2 context exists', async () => {
    setGpu(undefined);
    const fakeCanvas = { getContext: () => ({}) } as unknown as HTMLCanvasElement;
    spyOn(document, 'createElement').and.returnValue(fakeCanvas);

    const tier = await service.detect();

    expect(tier).toBe('webgl');
  });

  it('reports "none" when neither WebGPU nor WebGL is available', async () => {
    setGpu(undefined);
    const fakeCanvas = { getContext: () => null } as unknown as HTMLCanvasElement;
    spyOn(document, 'createElement').and.returnValue(fakeCanvas);

    const tier = await service.detect();

    expect(tier).toBe('none');
  });

  it('caches the detected tier and probes only once', async () => {
    setGpu({ requestAdapter: () => Promise.resolve({}) });

    const first = await service.detect();
    setGpu(undefined);
    const second = await service.detect();

    expect(second).toBe(first);
  });
});
