import { beforeEach, describe, expect, it, vi } from 'vitest';
import { ensureCoverTierJs } from './resolveJs';
import type { CoverArtRef } from './types';

vi.mock('../utils/imageCache', () => ({
  getCachedBlob: vi.fn(async () => new Blob(['x'], { type: 'image/jpeg' })),
}));

vi.mock('../utils/imageCache/coverSiblings', () => ({
  parseCoverCacheKey: (key: string) => {
    const m = key.match(/^(.+):cover:(.+):(.+):(\d+)$/);
    if (!m) return null;
    return { stem: `${m[1]}:cover:${m[2]}:${m[3]}`, size: Number(m[4]) };
  },
  probeSiblingCoverBlobInMemory: () => null,
  probeSiblingCoverBlobFromIDB: async () => null,
  scheduleSiblingVersusNetworkRace: vi.fn(),
}));

const { blobMap } = vi.hoisted(() => ({ blobMap: new Map<string, Blob>() }));
vi.mock('../utils/imageCache/blobCache', () => ({
  blobCache: blobMap,
  rememberBlob: (key: string, blob: Blob) => {
    blobMap.set(key, blob);
  },
}));

vi.mock('../utils/imageCache/idbStore', () => ({
  putBlob: vi.fn(),
}));

vi.mock('./reachability', () => ({
  coverServerReachable: () => true,
}));

vi.mock('./fetchUrl', () => ({
  buildCoverArtFetchUrl: () => 'https://example.test/cover',
}));

const ref: CoverArtRef = {
  cacheKind: 'album',
  cacheEntityId: 'al-1',
  fetchCoverArtId: 'al-1',
  serverScope: { kind: 'active' },
};

describe('ensureCoverTierJs', () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  it('returns null when cover id missing', async () => {
    expect(await ensureCoverTierJs({ ...ref, fetchCoverArtId: '' }, 128)).toBeNull();
  });

  it('fetches via getCachedBlob on cold path', async () => {
    const { getCachedBlob } = await import('../utils/imageCache');
    vi.mocked(getCachedBlob).mockImplementation(async (_url, key) => {
      const b = new Blob(['x'], { type: 'image/jpeg' });
      blobMap.set(key, b);
      return b;
    });
    const blob = await ensureCoverTierJs(ref, 128);
    expect(blob).toBeTruthy();
    expect(getCachedBlob).toHaveBeenCalled();
  });
});
