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

vi.mock('../../../shared/state', async () => {
  const sendMessage = vi.fn();
  const escapeHtml = (s: string): string => s.replace(/[&<>"']/g, (c) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' }[c]!));
  return { sendMessage, escapeHtml, popOutToTab: vi.fn(), isInTab: vi.fn(() => false), openVaultTab: vi.fn() };
});

import { renderAttachmentsDisclosure, wireAttachmentsDisclosure } from '../attachments-disclosure';
import { sendMessage } from '../../../shared/state';
import type { AttachmentRef } from '../../../shared/types';

const REF1: AttachmentRef = { id: 'a1', filename: 'doc.pdf', mime_type: 'application/pdf', size: 12345, created: 1700000000 };
const REF2: AttachmentRef = { id: 'a2', filename: 'photo.png', mime_type: 'image/png', size: 240000, created: 1700000001 };

describe('attachments-disclosure render', () => {
  it('renders empty state with no rows in edit mode', () => {
    const html = renderAttachmentsDisclosure({ itemId: 'i1', attachments: [], mode: 'edit', onChange: vi.fn() });
    expect(html).toContain('attachments');
    expect(html).toContain('+ attach file');
    expect(html).not.toContain('attachment-row');
  });

  it('renders rows + remove buttons in edit mode', () => {
    const html = renderAttachmentsDisclosure({ itemId: 'i1', attachments: [REF1, REF2], mode: 'edit', onChange: vi.fn() });
    expect(html).toContain('doc.pdf');
    expect(html).toContain('photo.png');
    expect(html).toContain('×');
    expect(html).toContain('attachment-row__thumb');  // image-mime row gets thumb hook
  });

  it('renders rows + download buttons in view mode (no add btn)', () => {
    const html = renderAttachmentsDisclosure({ itemId: 'i1', attachments: [REF1], mode: 'view' });
    expect(html).toContain('↓');
    expect(html).not.toContain('+ attach file');
  });
});

describe('attachments-disclosure wiring', () => {
  beforeEach(() => {
    vi.mocked(sendMessage).mockReset();
  });

  it('clicking + attach triggers file input click', () => {
    document.body.innerHTML = renderAttachmentsDisclosure({ itemId: 'i1', attachments: [], mode: 'edit', onChange: vi.fn() });
    const fileInput = document.querySelector('.attachments-disclosure__file-input') as HTMLInputElement;
    const clickSpy = vi.spyOn(fileInput, 'click');
    wireAttachmentsDisclosure(document.body, { itemId: 'i1', attachments: [], mode: 'edit', onChange: vi.fn() });
    (document.querySelector('.attachment-add-btn') as HTMLButtonElement).click();
    expect(clickSpy).toHaveBeenCalled();
  });

  it('clicking × calls onChange with the attachment removed', () => {
    const onChange = vi.fn();
    document.body.innerHTML = renderAttachmentsDisclosure({ itemId: 'i1', attachments: [REF1, REF2], mode: 'edit', onChange });
    wireAttachmentsDisclosure(document.body, { itemId: 'i1', attachments: [REF1, REF2], mode: 'edit', onChange });
    (document.querySelectorAll('.attachment-row__remove')[0] as HTMLElement).click();
    expect(onChange).toHaveBeenCalledWith([REF2]);
  });

  it('clicking ↓ in view mode sends download_attachment', async () => {
    vi.mocked(sendMessage).mockResolvedValueOnce({ ok: true, data: { bytes: new ArrayBuffer(10), filename: 'doc.pdf', mimeType: 'application/pdf' } });
    document.body.innerHTML = renderAttachmentsDisclosure({ itemId: 'i1', attachments: [REF1], mode: 'view' });
    wireAttachmentsDisclosure(document.body, { itemId: 'i1', attachments: [REF1], mode: 'view' });
    (document.querySelector('.attachment-row__download') as HTMLElement).click();
    await new Promise((r) => setTimeout(r, 50));
    expect(vi.mocked(sendMessage)).toHaveBeenCalledWith(expect.objectContaining({
      type: 'download_attachment',
      itemId: 'i1',
      attachmentId: 'a1',
    }));
  });
});
