/**
 * @license
 * Copyright 2026 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */

import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import { Config } from '../config/config.js';
import { MessageBus } from '../confirmation-bus/message-bus.js';
import type { PolicyEngine } from '../policy/policy-engine.js';
import {
  TrackerCreateTaskTool,
  TrackerListTasksTool,
  TrackerUpdateTaskTool,
  TrackerVisualizeTool,
  TrackerAddDependencyTool,
} from './trackerTools.js';
import * as fs from 'node:fs/promises';
import * as path from 'node:path';
import * as os from 'node:os';

import { TaskStatus, TaskType } from '../services/trackerTypes.js';

describe('Tracker Tools Integration', () => {
  let tempDir: string;
  let config: Config;
  let messageBus: MessageBus;

  beforeEach(async () => {
    tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'tracker-tools-test-'));
    config = new Config({
      sessionId: 'test-session',
      targetDir: tempDir,
      cwd: tempDir,
      model: 'gemini-3-flash',
      debugMode: false,
    });
    messageBus = new MessageBus(null as unknown as PolicyEngine, false);
  });

  afterEach(async () => {
    await fs.rm(tempDir, { recursive: true, force: true });
  });

  const getSignal = () => new AbortController().signal;

  it('creates and lists tasks', async () => {
    const createTool = new TrackerCreateTaskTool(config, messageBus);
    const createResult = await createTool.buildAndExecute(
      {
        title: 'Test Task',
        description: 'Test Description',
        type: TaskType.TASK,
      },
      getSignal(),
    );

    expect(createResult.llmContent).toContain('Created task');

    const listTool = new TrackerListTasksTool(config, messageBus);
    const listResult = await listTool.buildAndExecute({}, getSignal());
    expect(listResult.llmContent).toContain('Test Task');
    expect(listResult.llmContent).toContain(`(${TaskStatus.OPEN})`);
  });

  it('updates task status', async () => {
    const createTool = new TrackerCreateTaskTool(config, messageBus);
    await createTool.buildAndExecute(
      {
        title: 'Update Me',
        description: '...',
        type: TaskType.TASK,
      },
      getSignal(),
    );

    const tasks = await config.getTrackerService().listTasks();
    const taskId = tasks[0].id;

    const updateTool = new TrackerUpdateTaskTool(config, messageBus);
    const updateResult = await updateTool.buildAndExecute(
      {
        id: taskId,
        status: TaskStatus.IN_PROGRESS,
      },
      getSignal(),
    );

    expect(updateResult.llmContent).toContain(
      `Status: ${TaskStatus.IN_PROGRESS}`,
    );

    const task = await config.getTrackerService().getTask(taskId);
    expect(task?.status).toBe(TaskStatus.IN_PROGRESS);
  });

  it('adds dependencies and visualizes the graph', async () => {
    const createTool = new TrackerCreateTaskTool(config, messageBus);

    // Create Parent
    await createTool.buildAndExecute(
      {
        title: 'Parent Task',
        description: '...',
        type: TaskType.TASK,
      },
      getSignal(),
    );

    // Create Child
    await createTool.buildAndExecute(
      {
        title: 'Child Task',
        description: '...',
        type: TaskType.TASK,
      },
      getSignal(),
    );

    const tasks = await config.getTrackerService().listTasks();
    const parentId = tasks.find((t) => t.title === 'Parent Task')!.id;
    const childId = tasks.find((t) => t.title === 'Child Task')!.id;

    // Add Dependency
    const addDepTool = new TrackerAddDependencyTool(config, messageBus);
    await addDepTool.buildAndExecute(
      {
        taskId: parentId,
        dependencyId: childId,
      },
      getSignal(),
    );

    const updatedParent = await config.getTrackerService().getTask(parentId);
    expect(updatedParent?.dependencies).toContain(childId);

    // Visualize
    const vizTool = new TrackerVisualizeTool(config, messageBus);
    const vizResult = await vizTool.buildAndExecute({}, getSignal());

    expect(vizResult.llmContent).toContain('Parent Task');
    expect(vizResult.llmContent).toContain('Child Task');
    expect(vizResult.llmContent).toContain(childId);
  });
});
