import { describe, expect, it } from 'vitest';
import { handleGetVaultStatus } from '../../service-worker/vault';
import { renderStatusIndicator } from '../vault-status';
import type { Manifest, ManifestEntry } from '../../shared/types';

// Integration seam: the get_vault_status SW handler (Phase 6 Task 6.1) produces
// the exact data shape the sidebar renderer (Task 6.2) consumes. This pins the
// contract between the two so a future change to either side can't silently
// drift the keys apart. It does NOT touch vault-sidebar.ts — the wiring layer
// (Task 6.3) is Dev-B's boundary and lands separately.

const cache = (lastSyncAt: number | null, ahead = 0, behind = 0) =>
  ({ lastSyncAt, ahead, behind });

function manifestWith(activeCount: number, trashedCount = 0): Manifest {
  const items: Record<string, ManifestEntry> = {};
  for (let i = 0; i < activeCount; i++) {
    items[`a${i}`] = { trashed_at: undefined } as ManifestEntry;
  }
  for (let i = 0; i < trashedCount; i++) {
    items[`t${i}`] = { trashed_at: 1000 } as ManifestEntry;
  }
  return { items } as Manifest;
}

describe('vault status: handler → renderer integration', () => {
  it('renders "in sync" from a freshly-synced, no-pending handler response', () => {
    const resp = handleGetVaultStatus({ gitHost: cache(1700000000), manifest: manifestWith(0) });
    expect(resp.ok).toBe(true);
    if (!resp.ok) return;
    const el = document.createElement('div');
    renderStatusIndicator(el, resp.data);
    expect(el.textContent).toMatch(/in sync/i);
    expect(el.textContent).toMatch(/last sync/i);
  });

  it('surfaces the handler\'s active-item count as "N pending" in the DOM', () => {
    const resp = handleGetVaultStatus({ gitHost: cache(1700000000), manifest: manifestWith(7, 3) });
    expect(resp.ok).toBe(true);
    if (!resp.ok) return;
    expect(resp.data.pendingItems).toBe(7);
    const el = document.createElement('div');
    renderStatusIndicator(el, resp.data);
    expect(el.textContent).toMatch(/7 pending/i);
  });

  it('surfaces cached ahead/behind from the handler in the DOM', () => {
    const resp = handleGetVaultStatus({ gitHost: cache(1700000000, 2, 1), manifest: manifestWith(0) });
    expect(resp.ok).toBe(true);
    if (!resp.ok) return;
    const el = document.createElement('div');
    renderStatusIndicator(el, resp.data);
    expect(el.textContent).toMatch(/2 ahead/i);
    expect(el.textContent).toMatch(/1 behind/i);
  });

  it('renders "never synced" when the handler reports a null lastSyncAt', () => {
    const resp = handleGetVaultStatus({ gitHost: cache(null), manifest: manifestWith(0) });
    expect(resp.ok).toBe(true);
    if (!resp.ok) return;
    const el = document.createElement('div');
    renderStatusIndicator(el, resp.data);
    expect(el.textContent).toMatch(/never synced/i);
  });
});
