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

import { openDmsFilePreview, supportsOnlyOfficePreview } from '../dmsFilePreview';

const mocks = vi.hoisted(() => ({
  createTicket: vi.fn(),
  openOfficeDocument: vi.fn(),
}));

vi.mock('#/api/x/dms/preview', () => ({
  createDmsFilePreviewTicket: mocks.createTicket,
}));

vi.mock('#/utils/jnpf', () => ({
  onlineUtils: { openOfficeDocument: mocks.openOfficeDocument },
}));

describe('dMS OnlyOffice preview', () => {
  beforeEach(() => {
    mocks.createTicket.mockReset();
    mocks.openOfficeDocument.mockReset();
    vi.stubGlobal('crypto', { randomUUID: () => '018f0000-0000-7000-8000-000000000703' });
  });

  afterEach(() => {
    vi.unstubAllGlobals();
  });

  it('rejects unsupported file extensions before requesting a ticket', async () => {
    expect(supportsOnlyOfficePreview('archive.zip')).toBe(false);

    await expect(openDmsFilePreview({ fileName: 'archive.zip', resourceId: 'version-1', resourceType: 'FILE_VERSION' })).rejects.toThrow(
      'OnlyOffice 不支持该文件格式',
    );
    expect(mocks.createTicket).not.toHaveBeenCalled();
  });

  it('requests a ticket and opens the global modal in DMS view mode', async () => {
    mocks.createTicket.mockResolvedValue({
      data: {
        accessTicket: 'ticket-1',
        expiresAt: '2026-08-24T12:05:00Z',
        fileName: 'quality-manual.docx',
        fileVersionId: 'version-1',
        sizeBytes: 2048,
      },
    });

    await openDmsFilePreview({
      fileName: 'quality-manual.docx',
      resourceId: 'document-1',
      resourceType: 'DOCUMENT',
    });

    expect(mocks.createTicket).toHaveBeenCalledWith({
      operationId: '018f0000-0000-7000-8000-000000000703',
      resourceId: 'document-1',
      resourceType: 'DOCUMENT',
    });
    expect(mocks.openOfficeDocument).toHaveBeenCalledWith({
      dmsAccessTicket: 'ticket-1',
      file: {
        fileId: 'version-1',
        fileSize: 2048,
        name: 'quality-manual.docx',
      },
      fileType: 'dms',
      mode: 'view',
      title: 'quality-manual.docx',
    });
  });

  it('does not request a second ticket while the same resource is opening', async () => {
    let resolveTicket: (value: unknown) => void = () => {};
    mocks.createTicket.mockReturnValue(new Promise((resolve) => (resolveTicket = resolve)));
    const options = { fileName: 'quality-manual.docx', resourceId: 'version-1', resourceType: 'FILE_VERSION' as const };

    const first = openDmsFilePreview(options);
    const second = openDmsFilePreview(options);

    await expect(second).resolves.toBe(false);
    expect(mocks.createTicket).toHaveBeenCalledTimes(1);

    resolveTicket({
      data: {
        accessTicket: 'ticket-1',
        expiresAt: '2026-08-24T12:05:00Z',
        fileName: 'quality-manual.docx',
        fileVersionId: 'version-1',
      },
    });
    await first;
    expect(mocks.openOfficeDocument).toHaveBeenCalledTimes(1);
  });
});
