import { z } from 'zod';
import { readFile } from 'node:fs/promises';
import type { ToolDef, ToolContext } from './types.js';
import { resolveWritePath } from '../write_guard.js';
import { lspManager } from '../lsp/server-manager.js';
import { gotoDefinition } from '../lsp/operations.js';

const LspGotoDefinitionInput = z.object({
  file_path: z.string().describe('Path to the source file'),
  line: z.number().int().nonnegative().describe('0-based line number'),
  character: z.number().int().nonnegative().describe('0-based character offset'),
});

type InputT = z.infer<typeof LspGotoDefinitionInput>;

export const lspGotoDefinitionTool: ToolDef<InputT> = {
  name: 'lsp_goto_definition',
  description: 'Find the definition of a symbol at a given position in a file.',
  inputSchema: LspGotoDefinitionInput,
  jsonSchema: {
    type: 'function',
    function: {
      name: 'lsp_goto_definition',
      description: 'Find definition of symbol at position',
      parameters: {
        type: 'object',
        properties: {
          file_path: { type: 'string' },
          line: { type: 'number' },
          character: { type: 'number' },
        },
        required: ['file_path', 'line', 'character'],
      },
    },
  },

  async execute(input: InputT, projectRoot: string, _context: ToolContext): Promise<unknown> {
    const resolved = await resolveWritePath(projectRoot, input.file_path);
    const content = await readFile(resolved, 'utf8');
    const client = await lspManager.getClient(resolved);
    if (!client) return { error: 'Unsupported file type' };

    const loc = await gotoDefinition(client, resolved, content, input.line, input.character);
    if (!loc) return { result: 'No definition found.' };

    return { result: `Defined at ${loc.uri}:${loc.range.start.line + 1}:${loc.range.start.character + 1}` };
  },
};
