import React, { act } from 'react';
import { createRoot } from 'react-dom/client';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';

import {
  MemberWorkSyncBadge,
  MemberWorkSyncDetails,
  MemberWorkSyncStatusPanel,
  useMemberWorkSyncStatus,
} from '@features/member-work-sync/renderer';

import type { MemberWorkSyncStatus } from '@features/member-work-sync/contracts';

const apiMocks = vi.hoisted(() => ({
  getStatus: vi.fn(),
}));

vi.mock('@renderer/api', () => ({
  api: {
    memberWorkSync: {
      getStatus: apiMocks.getStatus,
    },
  },
  isElectronMode: () => true,
}));

function makeStatus(overrides: Partial<MemberWorkSyncStatus> = {}): MemberWorkSyncStatus {
  return {
    teamName: 'team-a',
    memberName: 'bob',
    state: 'needs_sync',
    agenda: {
      teamName: 'team-a',
      memberName: 'bob',
      generatedAt: '2026-04-29T00:00:00.000Z',
      fingerprint: 'agenda:v1:abcdef1234567890',
      items: [
        {
          taskId: 'task-1',
          displayId: '11111111',
          subject: 'Ship UI',
          kind: 'work',
          assignee: 'bob',
          priority: 'normal',
          reason: 'owned_pending_task',
          evidence: { status: 'pending', owner: 'bob' },
        },
      ],
      diagnostics: [],
    },
    shadow: {
      reconciledBy: 'queue',
      wouldNudge: true,
      fingerprintChanged: false,
    },
    evaluatedAt: '2026-04-29T00:00:00.000Z',
    diagnostics: ['developer_only'],
    ...overrides,
  };
}

describe('member work sync renderer', () => {
  beforeEach(() => {
    vi.clearAllMocks();
    vi.stubGlobal('IS_REACT_ACT_ENVIRONMENT', true);
  });

  afterEach(() => {
    document.body.innerHTML = '';
    vi.unstubAllGlobals();
  });

  it('loads read-only status through the renderer hook', async () => {
    apiMocks.getStatus.mockResolvedValue(makeStatus());
    const host = document.createElement('div');
    document.body.appendChild(host);
    const root = createRoot(host);

    function Harness(): React.ReactElement {
      const state = useMemberWorkSyncStatus({ teamName: 'team-a', memberName: 'bob' });
      return React.createElement('div', null, state.loading ? 'Loading' : state.viewModel.label);
    }

    await act(async () => {
      root.render(React.createElement(Harness));
      await Promise.resolve();
    });

    expect(apiMocks.getStatus).toHaveBeenCalledWith({ teamName: 'team-a', memberName: 'bob' });
    expect(host.textContent).toContain('Needs sync');
  });

  it('renders neutral diagnostics without exposing raw diagnostics by default', async () => {
    const host = document.createElement('div');
    document.body.appendChild(host);
    const root = createRoot(host);

    await act(async () => {
      root.render(
        React.createElement(
          'div',
          null,
          React.createElement(MemberWorkSyncBadge, { status: makeStatus() }),
          React.createElement(MemberWorkSyncDetails, { status: makeStatus() })
        )
      );
    });

    expect(host.textContent).toContain('Needs sync');
    expect(host.textContent).toContain('Shadow would nudge');
    expect(host.textContent).toContain('11111111');
    expect(host.textContent).not.toContain('developer_only');
  });

  it('renders the status panel through the read-only API hook', async () => {
    apiMocks.getStatus.mockResolvedValue(makeStatus());
    const host = document.createElement('div');
    document.body.appendChild(host);
    const root = createRoot(host);

    await act(async () => {
      root.render(
        React.createElement(MemberWorkSyncStatusPanel, {
          teamName: 'team-a',
          memberName: 'bob',
        })
      );
      await Promise.resolve();
    });

    expect(host.textContent).toContain('Member work sync');
    expect(host.textContent).toContain('Needs sync');
    expect(host.textContent).toContain('Shadow would nudge');
    expect(apiMocks.getStatus).toHaveBeenCalledWith({ teamName: 'team-a', memberName: 'bob' });
  });
});
