import { normalizeSkillProcessLine } from '../src/modules/netaclaw/service/skill_executor';

describe('skill process events', () => {
  it('only parses explicit process_event JSON lines', () => {
    const event = normalizeSkillProcessLine(
      'vehicle-damage-inspection',
      '{"type":"process_event","stage":"inspect","message":"Inspecting","taskId":"task-1","status":"completed","level":"warning","current":2,"total":4,"percent":55,"timestamp":"2026-05-06T00:00:00.000Z","note":"kept"}',
      7,
    );

    expect(event).toEqual({
      source: 'skill',
      targetType: 'skill',
      taskId: 'task-1',
      stage: 'inspect',
      status: 'completed',
      level: 'warning',
      message: 'Inspecting',
      timestamp: '2026-05-06T00:00:00.000Z',
      sequence: 7,
      current: 2,
      total: 4,
      percent: 55,
      payload: { note: 'kept' },
    });
  });

  it('supports bracketed stderr prefixes before JSON', () => {
    const event = normalizeSkillProcessLine(
      'vehicle-damage-inspection',
      '[vehicle-damage-inspection] {"type":"process_event","stage":"upload","time":"2026-05-06T00:00:00.000Z"}',
      1,
    );

    expect(event).toEqual(expect.objectContaining({
      source: 'skill',
      targetType: 'skill',
      stage: 'upload',
      status: 'running',
      level: 'info',
      message: 'upload',
      timestamp: '2026-05-06T00:00:00.000Z',
      sequence: 1,
    }));
  });

  it('derives percent from batch and totalBatches', () => {
    const event = normalizeSkillProcessLine(
      'vehicle-damage-inspection',
      '{"type":"process_event","stage":"batching","batch":1,"totalBatches":3}',
      2,
    );

    expect(event).toEqual(expect.objectContaining({
      current: 1,
      total: 3,
      percent: 33,
    }));
  });

  it('sanitizes payload before emitting process events', () => {
    const event = normalizeSkillProcessLine(
      'vehicle-damage-inspection',
      JSON.stringify({
        type: 'process_event',
        message: 'request completed',
        apiKey: 'secret',
        rawText: 'x'.repeat(600),
        nested: { value: 1 },
      }),
      3,
    );

    expect(event?.payload).toEqual({
      apiKey: '[filtered]',
      rawText: `${'x'.repeat(500)}...`,
      nested: '[object]',
    });
  });

  it('returns null for ordinary stderr', () => {
    expect(normalizeSkillProcessLine(
      'vehicle-damage-inspection',
      'Traceback: failed to import module',
      1,
    )).toBeNull();
  });

  it('returns null for ordinary JSON without process_event type', () => {
    expect(normalizeSkillProcessLine(
      'vehicle-damage-inspection',
      '{"stage":"inspect","message":"ordinary json"}',
      1,
    )).toBeNull();
  });
});

describe('vehicle damage inspection process event output', () => {
  it('main skill progress logs are explicit process events', async () => {
    const scriptPath = require.resolve('../skills/vehicle-damage-inspection/scripts/index.cjs');
    const originalWrite = process.stderr.write;
    const writes: string[] = [];
    jest.resetModules();
    process.stderr.write = jest.fn((chunk: any) => {
      writes.push(String(chunk));
      return true;
    }) as any;

    try {
      const skill = require(scriptPath);
      await skill.run(
        { videoUrl: 'demo.mp4', taskId: 'task-1', mode: 'frames-only' },
        {
          RZYX_AI_WORKSPACE_ROOT: 'C:/data/workspace/vehicle-damage-inspection',
          RZYX_AI_UPLOAD_ROOT: 'C:/data/uploads',
        },
        {
          createWorkspace: () => ({
            taskId: 'task-1',
            workspacePath: 'C:/data/workspace/vehicle-damage-inspection/task-1',
          }),
          resolveVideoPath: () => 'C:/data/uploads/demo.mp4',
          extractFrames: async () => ({
            videoInfo: { duration: 1, resolution: '960x544', extractedFrames: 1 },
            frames: [{ index: 0, timestamp: 0, path: 'frame.jpg' }],
          }),
          writeJson: () => undefined,
        },
      );
    } finally {
      process.stderr.write = originalWrite;
    }

    const parsed = writes
      .map(line => line.match(/\[vehicle-damage-inspection\]\s*(\{.*\})/)?.[1])
      .filter(Boolean)
      .map(json => JSON.parse(json as string));
    expect(parsed.length).toBeGreaterThan(0);
    expect(parsed.every(item => item.type === 'process_event')).toBe(true);
  });
});
