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

import { OpenCodeTurnSettledPayloadNormalizer } from '@features/member-work-sync/main/infrastructure/OpenCodeTurnSettledPayloadNormalizer';
import { NodeHashAdapter } from '@features/member-work-sync/main/infrastructure/NodeHashAdapter';

describe('OpenCodeTurnSettledPayloadNormalizer', () => {
  it('normalizes orchestrator-native OpenCode turn-settled payloads', () => {
    const normalizer = new OpenCodeTurnSettledPayloadNormalizer(new NodeHashAdapter());

    const result = normalizer.normalize({
      provider: 'opencode',
      raw: JSON.stringify({
        schemaVersion: 1,
        provider: 'opencode',
        source: 'agent-teams-orchestrator-opencode',
        eventName: 'runtime_turn_settled',
        hookEventName: 'Stop',
        sessionId: 'ses-opencode-1',
        runtimePromptMessageId: 'msg_123',
        laneId: 'lane-jack',
        memberName: 'jack',
        teamName: 'team-a',
        projectPath: '/tmp/project',
        outcome: 'success',
        observedAt: '2026-04-29T12:00:00.000Z',
      }),
      recordedAt: '2026-04-29T12:00:01.000Z',
    });

    expect(result).toEqual({
      ok: true,
      event: expect.objectContaining({
        provider: 'opencode',
        hookEventName: 'Stop',
        sessionId: 'ses-opencode-1',
        turnId: 'msg_123',
        threadId: 'msg_123',
        teamName: 'team-a',
        memberName: 'jack',
        agentId: 'lane-jack',
        cwd: '/tmp/project',
        outcome: 'success',
        recordedAt: '2026-04-29T12:00:00.000Z',
      }),
    });
  });

  it('rejects OpenCode payloads without durable team/member identity', () => {
    const normalizer = new OpenCodeTurnSettledPayloadNormalizer(new NodeHashAdapter());

    expect(
      normalizer.normalize({
        provider: 'opencode',
        raw: JSON.stringify({
          provider: 'opencode',
          source: 'agent-teams-orchestrator-opencode',
          eventName: 'runtime_turn_settled',
          sessionId: 'ses-opencode-1',
        }),
        recordedAt: '2026-04-29T12:00:01.000Z',
      })
    ).toEqual({ ok: false, reason: 'missing_team_member_identity' });
  });

  it('rejects payloads from non-agent-teams OpenCode sources', () => {
    const normalizer = new OpenCodeTurnSettledPayloadNormalizer(new NodeHashAdapter());

    expect(
      normalizer.normalize({
        provider: 'opencode',
        raw: JSON.stringify({
          provider: 'opencode',
          source: 'some-other-source',
          eventName: 'runtime_turn_settled',
          sessionId: 'ses-opencode-1',
          teamName: 'team-a',
          memberName: 'jack',
        }),
        recordedAt: '2026-04-29T12:00:01.000Z',
      })
    ).toEqual({ ok: false, reason: 'source_mismatch' });
  });
});
