import { describe, it, expect, vi, afterEach } from 'vitest';
import {
  isViewableImagingFile,
  imagingFormatOf,
  fetchAsFile,
  VIEWABLE_IMAGING_EXTENSIONS,
} from './imagehubViewer';

describe('isViewableImagingFile', () => {
  it('accepts DICOM + NIfTI extensions (case-insensitive)', () => {
    expect(isViewableImagingFile('brain.nii')).toBe(true);
    expect(isViewableImagingFile('brain.nii.gz')).toBe(true);
    expect(isViewableImagingFile('slice.dcm')).toBe(true);
    expect(isViewableImagingFile('SCAN.DICOM')).toBe(true);
    expect(isViewableImagingFile('CT_0001.DCM')).toBe(true);
  });

  it('rejects non-imaging files and empty/nullish input', () => {
    expect(isViewableImagingFile('report.pdf')).toBe(false);
    expect(isViewableImagingFile('notes.txt')).toBe(false);
    expect(isViewableImagingFile('archive.nii.zip')).toBe(false);
    expect(isViewableImagingFile('')).toBe(false);
    // @ts-expect-error — guard the runtime null path
    expect(isViewableImagingFile(null)).toBe(false);
  });

  it('covers every advertised extension', () => {
    for (const ext of VIEWABLE_IMAGING_EXTENSIONS) {
      expect(isViewableImagingFile(`file${ext}`)).toBe(true);
    }
  });
});

describe('imagingFormatOf', () => {
  it('routes NIfTI (incl. .nii.gz, case-insensitive)', () => {
    expect(imagingFormatOf('a.nii')).toBe('nifti');
    expect(imagingFormatOf('a.NII.GZ')).toBe('nifti');
  });

  it('routes DICOM', () => {
    expect(imagingFormatOf('a.dcm')).toBe('dicom');
    expect(imagingFormatOf('a.dicom')).toBe('dicom');
  });

  it('returns null for unknown / empty', () => {
    expect(imagingFormatOf('a.png')).toBeNull();
    expect(imagingFormatOf('')).toBeNull();
  });
});

describe('fetchAsFile', () => {
  afterEach(() => vi.unstubAllGlobals());

  it('wraps fetched bytes in a File, preserving the name (needed for format detection)', async () => {
    const bytes = new Uint8Array([1, 2, 3, 4]);
    vi.stubGlobal('fetch', vi.fn(async () => new Response(bytes, { status: 200 })));
    const file = await fetchAsFile('https://example/blob', 'brain.nii.gz');
    expect(file).toBeInstanceOf(File);
    expect(file.name).toBe('brain.nii.gz');
    expect(file.size).toBe(4);
  });

  it('honours an explicit media type', async () => {
    vi.stubGlobal('fetch', vi.fn(async () => new Response(new Uint8Array([0]), { status: 200 })));
    const file = await fetchAsFile('u', 'x.dcm', 'application/dicom');
    expect(file.type).toBe('application/dicom');
  });

  it('throws on a non-ok response (surfacing the status)', async () => {
    vi.stubGlobal('fetch', vi.fn(async () => new Response('nope', { status: 404 })));
    await expect(fetchAsFile('u', 'x.nii')).rejects.toThrow(/404/);
  });
});
