import { Type } from '@sinclair/typebox';
import type { ToolDefinition } from '@mariozechner/pi-coding-agent';
import type { Brain } from '@mosaicstack/brain';

export function createBrainTools(brain: Brain): ToolDefinition[] {
  const listProjects: ToolDefinition = {
    name: 'brain_list_projects',
    label: 'List Projects',
    description: 'List all projects in the brain.',
    parameters: Type.Object({}),
    async execute() {
      const projects = await brain.projects.findAll();
      return {
        content: [{ type: 'text' as const, text: JSON.stringify(projects, null, 2) }],
        details: undefined,
      };
    },
  };

  const getProject: ToolDefinition = {
    name: 'brain_get_project',
    label: 'Get Project',
    description: 'Get a project by ID.',
    parameters: Type.Object({
      id: Type.String({ description: 'Project ID (UUID)' }),
    }),
    async execute(_toolCallId, params) {
      const { id } = params as { id: string };
      const project = await brain.projects.findById(id);
      return {
        content: [
          {
            type: 'text' as const,
            text: project ? JSON.stringify(project, null, 2) : `Project not found: ${id}`,
          },
        ],
        details: undefined,
      };
    },
  };

  const listTasks: ToolDefinition = {
    name: 'brain_list_tasks',
    label: 'List Tasks',
    description: 'List tasks, optionally filtered by project, mission, or status.',
    parameters: Type.Object({
      projectId: Type.Optional(Type.String({ description: 'Filter by project ID' })),
      missionId: Type.Optional(Type.String({ description: 'Filter by mission ID' })),
      status: Type.Optional(Type.String({ description: 'Filter by status' })),
    }),
    async execute(_toolCallId, params) {
      const p = params as { projectId?: string; missionId?: string; status?: string };
      type TaskStatus = 'not-started' | 'in-progress' | 'blocked' | 'done' | 'cancelled';
      let tasks;
      if (p.projectId) tasks = await brain.tasks.findByProject(p.projectId);
      else if (p.missionId) tasks = await brain.tasks.findByMission(p.missionId);
      else if (p.status) tasks = await brain.tasks.findByStatus(p.status as TaskStatus);
      else tasks = await brain.tasks.findAll();
      return {
        content: [{ type: 'text' as const, text: JSON.stringify(tasks, null, 2) }],
        details: undefined,
      };
    },
  };

  const createTask: ToolDefinition = {
    name: 'brain_create_task',
    label: 'Create Task',
    description: 'Create a new task in the brain.',
    parameters: Type.Object({
      title: Type.String({ description: 'Task title' }),
      description: Type.Optional(Type.String({ description: 'Task description' })),
      projectId: Type.Optional(Type.String({ description: 'Project ID' })),
      missionId: Type.Optional(Type.String({ description: 'Mission ID' })),
      priority: Type.Optional(
        Type.String({ description: 'Priority: low, medium, high, critical' }),
      ),
    }),
    async execute(_toolCallId, params) {
      const p = params as {
        title: string;
        description?: string;
        projectId?: string;
        missionId?: string;
        priority?: string;
      };
      type Priority = 'low' | 'medium' | 'high' | 'critical';
      const task = await brain.tasks.create({
        ...p,
        priority: p.priority as Priority | undefined,
      });
      return {
        content: [{ type: 'text' as const, text: JSON.stringify(task, null, 2) }],
        details: undefined,
      };
    },
  };

  const updateTask: ToolDefinition = {
    name: 'brain_update_task',
    label: 'Update Task',
    description: 'Update an existing task.',
    parameters: Type.Object({
      id: Type.String({ description: 'Task ID' }),
      title: Type.Optional(Type.String()),
      description: Type.Optional(Type.String()),
      status: Type.Optional(
        Type.String({ description: 'not-started, in-progress, blocked, done, cancelled' }),
      ),
      priority: Type.Optional(Type.String()),
    }),
    async execute(_toolCallId, params) {
      const { id, ...updates } = params as {
        id: string;
        title?: string;
        description?: string;
        status?: string;
        priority?: string;
      };
      type TaskStatus = 'not-started' | 'in-progress' | 'blocked' | 'done' | 'cancelled';
      type Priority = 'low' | 'medium' | 'high' | 'critical';
      const task = await brain.tasks.update(id, {
        ...updates,
        status: updates.status as TaskStatus | undefined,
        priority: updates.priority as Priority | undefined,
      });
      return {
        content: [
          {
            type: 'text' as const,
            text: task ? JSON.stringify(task, null, 2) : `Task not found: ${id}`,
          },
        ],
        details: undefined,
      };
    },
  };

  const listMissions: ToolDefinition = {
    name: 'brain_list_missions',
    label: 'List Missions',
    description: 'List all missions, optionally filtered by project.',
    parameters: Type.Object({
      projectId: Type.Optional(Type.String({ description: 'Filter by project ID' })),
    }),
    async execute(_toolCallId, params) {
      const p = params as { projectId?: string };
      const missions = p.projectId
        ? await brain.missions.findByProject(p.projectId)
        : await brain.missions.findAll();
      return {
        content: [{ type: 'text' as const, text: JSON.stringify(missions, null, 2) }],
        details: undefined,
      };
    },
  };

  const listConversations: ToolDefinition = {
    name: 'brain_list_conversations',
    label: 'List Conversations',
    description: 'List conversations for a user.',
    parameters: Type.Object({
      userId: Type.String({ description: 'User ID' }),
    }),
    async execute(_toolCallId, params) {
      const { userId } = params as { userId: string };
      const conversations = await brain.conversations.findAll(userId);
      return {
        content: [{ type: 'text' as const, text: JSON.stringify(conversations, null, 2) }],
        details: undefined,
      };
    },
  };

  return [
    listProjects,
    getProject,
    listTasks,
    createTask,
    updateTask,
    listMissions,
    listConversations,
  ];
}
