import { beforeEach, describe, expect, it, vi } from 'vitest';
import type { TicketAttachment } from '@/features/tickets/types/ticket.types';
import { apiClient } from '@/shared/utils/api';
import {
  downloadAttachmentFile,
  fetchAttachmentBlob,
  openAttachmentInNewTab,
  toApiRelativePath,
} from '@/shared/utils/fetchAttachment';

vi.mock('@/shared/utils/api', () => ({
  apiClient: {
    get: vi.fn(),
  },
}));

const attachment: TicketAttachment = {
  id: 'att-1',
  file_name: 'report.pdf',
  file_size: 4096,
  mime_type: 'application/pdf',
};

describe('fetchAttachment', () => {
  beforeEach(() => {
    vi.clearAllMocks();
    vi.stubGlobal('open', vi.fn(() => ({ focus: vi.fn() })));
    Object.defineProperty(URL, 'createObjectURL', {
      configurable: true,
      value: vi.fn(() => 'blob:mock-url'),
    });
    Object.defineProperty(URL, 'revokeObjectURL', {
      configurable: true,
      value: vi.fn(),
    });
  });

  it('fetches attachment blobs through the authenticated API client', async () => {
    const blob = new Blob(['pdf'], { type: 'application/pdf' });
    vi.mocked(apiClient.get).mockResolvedValue({ data: blob });

    const result = await fetchAttachmentBlob(attachment, { inline: true });

    expect(apiClient.get).toHaveBeenCalledWith('/attachments/att-1/download?inline=1', {
      responseType: 'blob',
      headers: { Accept: '*/*' },
    });
    expect(result).toBe(blob);
  });

  it('opens inline attachments in a new tab from a blob URL', async () => {
    const blob = new Blob(['pdf'], { type: 'application/pdf' });
    vi.mocked(apiClient.get).mockResolvedValue({ data: blob });

    await openAttachmentInNewTab(attachment, { inline: true });

    expect(window.open).toHaveBeenCalledWith(expect.stringMatching(/^blob:/), '_blank', 'noopener,noreferrer');
  });

  it('uses apiClient for absolute same-origin attachment download URLs', async () => {
    const blob = new Blob(['pdf'], { type: 'application/pdf' });
    vi.mocked(apiClient.get).mockResolvedValue({ data: blob });

    await fetchAttachmentBlob(
      {
        ...attachment,
        download_url: 'https://mvhelpdesk.local/api/v1/attachments/att-1/download',
      },
      { inline: true },
    );

    expect(apiClient.get).toHaveBeenCalledWith('/attachments/att-1/download?inline=1', {
      responseType: 'blob',
      headers: { Accept: '*/*' },
    });
  });

  it('downloads attachments using a temporary anchor', async () => {
    const blob = new Blob(['pdf'], { type: 'application/pdf' });
    vi.mocked(apiClient.get).mockResolvedValue({ data: blob });
    const click = vi.fn();
    const remove = vi.fn();
    const link = { href: '', download: '', click, remove } as unknown as HTMLAnchorElement;
    const createElement = vi.spyOn(document, 'createElement').mockReturnValue(link);
    const appendChild = vi.spyOn(document.body, 'appendChild').mockImplementation(() => link);

    await downloadAttachmentFile(attachment);

    expect(link.download).toBe('report.pdf');
    expect(link.href).toMatch(/^blob:/);
    expect(click).toHaveBeenCalled();
    expect(remove).toHaveBeenCalled();

    createElement.mockRestore();
    appendChild.mockRestore();
  });

  it('normalizes absolute API download URLs to relative paths', () => {
    expect(
      toApiRelativePath('https://mvhelpdesk.local:8890/api/v1/attachments/att-1/download?inline=1'),
    ).toBe('/attachments/att-1/download?inline=1');
  });
});
