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

import {
  MEMBER_WORK_SYNC_GET_METRICS,
  MEMBER_WORK_SYNC_GET_STATUS,
  MEMBER_WORK_SYNC_REFRESH_STATUS,
  MEMBER_WORK_SYNC_REPORT,
} from '@features/member-work-sync/contracts';
import { createMemberWorkSyncBridge } from '@features/member-work-sync/preload';

import type {
  MemberWorkSyncMetricsRequest,
  MemberWorkSyncReportRequest,
  MemberWorkSyncStatusRequest,
} from '@features/member-work-sync/contracts';
import type { IpcRenderer } from 'electron';

describe('createMemberWorkSyncBridge', () => {
  it('invokes the status channel without changing the request payload', async () => {
    const request: MemberWorkSyncStatusRequest = { teamName: 'team-a', memberName: 'bob' };
    const response = { ok: true };
    const ipcRenderer = {
      invoke: vi.fn(async () => response),
    } as unknown as IpcRenderer;
    const bridge = createMemberWorkSyncBridge(ipcRenderer);

    await expect(bridge.getStatus(request)).resolves.toBe(response);

    expect(ipcRenderer.invoke).toHaveBeenCalledWith(MEMBER_WORK_SYNC_GET_STATUS, request);
  });

  it('invokes the metrics channel without changing the request payload', async () => {
    const request: MemberWorkSyncMetricsRequest = { teamName: 'team-a' };
    const response = { ok: true };
    const ipcRenderer = {
      invoke: vi.fn(async () => response),
    } as unknown as IpcRenderer;
    const bridge = createMemberWorkSyncBridge(ipcRenderer);

    await expect(bridge.getMetrics(request)).resolves.toBe(response);

    expect(ipcRenderer.invoke).toHaveBeenCalledWith(MEMBER_WORK_SYNC_GET_METRICS, request);
  });

  it('invokes the refresh status channel without changing the request payload', async () => {
    const request: MemberWorkSyncStatusRequest = { teamName: 'team-a', memberName: 'bob' };
    const response = { ok: true };
    const ipcRenderer = {
      invoke: vi.fn(async () => response),
    } as unknown as IpcRenderer;
    const bridge = createMemberWorkSyncBridge(ipcRenderer);

    await expect(bridge.refreshStatus(request)).resolves.toBe(response);

    expect(ipcRenderer.invoke).toHaveBeenCalledWith(MEMBER_WORK_SYNC_REFRESH_STATUS, request);
  });

  it('invokes the report channel without changing the request payload', async () => {
    const request: MemberWorkSyncReportRequest = {
      teamName: 'team-a',
      memberName: 'bob',
      state: 'blocked',
      agendaFingerprint: 'agenda:v1:test',
      taskIds: ['task-1'],
      note: 'waiting on reviewer',
      source: 'app',
    };
    const response = { accepted: true };
    const ipcRenderer = {
      invoke: vi.fn(async () => response),
    } as unknown as IpcRenderer;
    const bridge = createMemberWorkSyncBridge(ipcRenderer);

    await expect(bridge.report(request)).resolves.toBe(response);

    expect(ipcRenderer.invoke).toHaveBeenCalledWith(MEMBER_WORK_SYNC_REPORT, request);
  });

  it('propagates IPC rejections to the renderer caller', async () => {
    const failure = new Error('ipc failed');
    const ipcRenderer = {
      invoke: vi.fn(async () => {
        throw failure;
      }),
    } as unknown as IpcRenderer;
    const bridge = createMemberWorkSyncBridge(ipcRenderer);

    await expect(bridge.getStatus({ teamName: 'team-a', memberName: 'bob' })).rejects.toBe(failure);
  });
});
