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 { findReferences } from '../lsp/operations.js';

const LspFindReferencesInput = 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 LspFindReferencesInput>;

export const lspFindReferencesTool: ToolDef<InputT> = {
  name: 'lsp_find_references',
  description: 'Find all references to a symbol at a given position in a file.',
  inputSchema: LspFindReferencesInput,
  jsonSchema: {
    type: 'function',
    function: {
      name: 'lsp_find_references',
      description: 'Find all references to 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 refs = await findReferences(client, resolved, content, input.line, input.character);
    if (refs.length === 0) return { result: 'No references found.' };

    const lines = refs.map((r) => `${r.uri}:${r.range.start.line + 1}:${r.range.start.character + 1}`);
    return { result: `Found ${refs.length} reference(s):\n${lines.join('\n')}` };
  },
};
