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

vi.mock('../../../../shared/state', async () => {
  const navigate = vi.fn();
  const setState = vi.fn();
  const sendMessage = vi.fn();
  const getState = vi.fn(() => ({
    view: 'add', entries: [], selectedId: null, selectedItem: null, selectedIndex: 0,
    searchQuery: '', activeGroup: null, error: null, loading: false,
    capturedTabId: null, capturedUrl: '', newType: 'document',
  }));
  const escapeHtml = (s: string) => s
    .replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;').replace(/'/g, '&#39;');
  return { navigate, setState, sendMessage, getState, escapeHtml, popOutToTab: vi.fn(), isInTab: vi.fn(() => false), openVaultTab: vi.fn() };
});

import { renderForm } from '../document';
import { sendMessage } from '../../../../shared/state';
import type { Item, AttachmentRef } from '../../../../shared/types';

const PRIMARY: AttachmentRef = {
  id: 'primaryid',
  filename: 'passport.pdf',
  mime_type: 'application/pdf',
  size: 240000,
  created: 1700000000,
};

describe('Document form save', () => {
  beforeEach(() => {
    document.body.innerHTML = '<div id="app"></div>';
    vi.mocked(sendMessage).mockReset();
    vi.mocked(sendMessage).mockResolvedValue({ ok: true, data: { id: 'fakeid0000000000', items: [] } });
  });

  it('rejects save when primary_attachment is missing', async () => {
    const app = document.getElementById('app')!;
    renderForm(app, 'add', null);
    (document.getElementById('f-title') as HTMLInputElement).value = 'Passport';
    const alertSpy = vi.spyOn(window, 'alert').mockImplementation(() => {});
    document.getElementById('save-btn')!.click();
    await new Promise((r) => setTimeout(r, 50));
    expect(alertSpy).not.toHaveBeenCalled();
    // setState called with the error
    const { setState } = await import('../../../../shared/state');
    expect(vi.mocked(setState)).toHaveBeenCalledWith(
      expect.objectContaining({ error: expect.stringContaining('primary attachment') }),
    );
    const calls = vi.mocked(sendMessage).mock.calls;
    const addCall = calls.find(([msg]) => (msg as { type: string }).type === 'add_item');
    expect(addCall).toBeUndefined();
  });

  it('sends update_item with correct wire shape when valid', async () => {
    vi.mocked(sendMessage).mockResolvedValue({ ok: true, data: { id: 'fakeid0000000000', items: [] } });
    const existingDraft: Item = {
      id: 'docid',
      type: 'document',
      core: {
        type: 'document',
        filename: PRIMARY.filename,
        mime_type: PRIMARY.mime_type,
        primary_attachment: PRIMARY.id,
      },
      title: 'Passport',
      tags: [],
      favorite: false,
      created: 0,
      modified: 0,
      trashed_at: undefined,
      sections: [],
      attachments: [PRIMARY],
      field_history: {},
    };
    const app = document.getElementById('app')!;
    renderForm(app, 'edit', existingDraft);
    document.getElementById('save-btn')!.click();
    await new Promise((r) => setTimeout(r, 50));
    const calls = vi.mocked(sendMessage).mock.calls;
    const updateCall = calls.find(([msg]) => (msg as { type: string }).type === 'update_item');
    expect(updateCall).toBeDefined();
    const msg = updateCall![0] as { type: 'update_item'; item: any };
    expect(msg.item.core.primary_attachment).toBe(PRIMARY.id);
    expect(msg.item.core.type).toBe('document');
    expect(msg.item.attachments).toEqual([PRIMARY]);
    expect(msg.item.type).toBe('document');
  });
});
