import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
import { createReadRawSpanTool } from '../../../../src/context/ingest/tools/read-raw-span.tool.js';

describe('read_raw_span tool', () => {
  let stagedDir: string;

  beforeEach(async () => {
    stagedDir = await mkdtemp(join(tmpdir(), 'readspan-'));
    await mkdir(join(stagedDir, 'v'), { recursive: true });
    await writeFile(join(stagedDir, 'v', 'a.yml'), 'line1\nline2\nline3\nline4\nline5\n', 'utf-8');
  });

  afterEach(async () => rm(stagedDir, { recursive: true, force: true }));

  it('returns the requested 1-based inclusive line range', async () => {
    const tool = createReadRawSpanTool({ stagedDir, allowedPaths: new Set(['v/a.yml']) });
    const result = await (tool.execute as (...args: unknown[]) => unknown)(
      { path: 'v/a.yml', startLine: 2, endLine: 4 },
      { toolCallId: 't1', messages: [] },
    );
    expect(result).toBe('line2\nline3\nline4');
  });

  it('clamps endLine to the end of the file', async () => {
    const tool = createReadRawSpanTool({ stagedDir, allowedPaths: new Set(['v/a.yml']) });
    const result = await (tool.execute as (...args: unknown[]) => unknown)(
      { path: 'v/a.yml', startLine: 4, endLine: 99 },
      { toolCallId: 't1', messages: [] },
    );
    expect(result).toBe('line4\nline5');
  });

  it('rejects start > end', async () => {
    const tool = createReadRawSpanTool({ stagedDir, allowedPaths: new Set(['v/a.yml']) });
    const result = await (tool.execute as (...args: unknown[]) => unknown)(
      { path: 'v/a.yml', startLine: 5, endLine: 2 },
      { toolCallId: 't1', messages: [] },
    );
    expect(result).toMatch(/startLine must be/i);
  });

  it('rejects paths not in the allow-list', async () => {
    const tool = createReadRawSpanTool({ stagedDir, allowedPaths: new Set([]) });
    const result = await (tool.execute as (...args: unknown[]) => unknown)(
      { path: 'v/a.yml', startLine: 1, endLine: 1 },
      { toolCallId: 't1', messages: [] },
    );
    expect(result).toMatch(/not accessible/i);
  });
});
