import { describe, it, expect } from 'vitest';
import {
  mergeToolSnapshot,
  mapToolLifecycleStatus,
  snapshotToWireToolCall,
  synthesizeCanceledSnapshots,
} from '../acp-tool-snapshot.js';

describe('mergeToolSnapshot', () => {
  it('preserves stable toolCallId across updates', () => {
    const first = mergeToolSnapshot('tc-1', {
      toolCallId: 'tc-1',
      title: 'Read file',
      kind: 'read',
      status: 'in_progress',
      rawInput: { path: 'foo.ts' },
    });
    const merged = mergeToolSnapshot(
      'tc-1',
      {
        toolCallId: 'tc-1',
        title: 'Read file',
        status: 'completed',
        rawOutput: { content: 'hello' },
      },
      first,
    );
    expect(merged.toolCallId).toBe('tc-1');
    expect(merged.rawInput).toEqual({ path: 'foo.ts' });
    expect(merged.status).toBe('completed');
    expect(merged.rawOutput).toEqual({ content: 'hello' });
  });
});

describe('snapshotToWireToolCall', () => {
  it('embeds ACP lifecycle meta for UI merge', () => {
    const wire = snapshotToWireToolCall({
      toolCallId: 'tc-42',
      title: 'Edit',
      kind: 'edit',
      status: 'completed',
      rawInput: { path: 'a.ts' },
      rawOutput: 'ok',
    });
    expect(wire.id).toBe('tc-42');
    expect(wire.name).toBe('edit');
    expect(wire.args._acp).toMatchObject({ status: 'completed', title: 'Edit', output: 'ok' });
  });

  it('maps synthesized cancel to canceled lifecycle', () => {
    const [canceled] = synthesizeCanceledSnapshots([
      { toolCallId: 'tc-1', title: 'Run', status: 'in_progress' },
    ]);
    const wire = snapshotToWireToolCall(canceled!);
    expect(wire.args._acp).toMatchObject({ status: 'canceled' });
  });
});

describe('mapToolLifecycleStatus', () => {
  it('maps ACP statuses to UI lifecycle', () => {
    expect(mapToolLifecycleStatus('completed')).toBe('completed');
    expect(mapToolLifecycleStatus('failed')).toBe('failed');
    expect(mapToolLifecycleStatus('in_progress')).toBe('running');
    expect(mapToolLifecycleStatus(undefined, 'canceled')).toBe('canceled');
  });
});
