import type { LspClient } from './client.js';
import type { Diagnostic, Location } from './types.js';

function fileUri(filePath: string): string {
  return `file://${filePath.startsWith('/') ? '' : '/'}${filePath}`;
}

export async function openDocument(
  client: LspClient,
  filePath: string,
  content: string,
  version: number = 1,
): Promise<void> {
  const uri = fileUri(filePath);
  await client.notify('textDocument/didOpen', {
    textDocument: { uri, languageId: 'typescript', version, text: content },
  });
}

export async function closeDocument(client: LspClient, filePath: string): Promise<void> {
  await client.notify('textDocument/didClose', {
    textDocument: { uri: fileUri(filePath) },
  });
}

export async function getDiagnostics(
  client: LspClient,
  filePath: string,
  content: string,
): Promise<Diagnostic[]> {
  const uri = fileUri(filePath);
  await openDocument(client, filePath, content);
  const result: any = await client.request('textDocument/diagnostic', {
    textDocument: { uri },
  });
  await closeDocument(client, filePath);
  const diagnostics: Diagnostic[] = [];
  if (result?.diagnostics) {
    for (const d of result.diagnostics) {
      diagnostics.push({
        range: d.range,
        severity: d.severity ?? 1,
        message: d.message,
        source: d.source,
      });
    }
  }
  return diagnostics;
}

export async function gotoDefinition(
  client: LspClient,
  filePath: string,
  content: string,
  line: number,
  character: number,
): Promise<Location | null> {
  const uri = fileUri(filePath);
  await openDocument(client, filePath, content);
  const result: any = await client.request('textDocument/definition', {
    textDocument: { uri },
    position: { line, character },
  });
  await closeDocument(client, filePath);
  if (!result) return null;
  const loc = Array.isArray(result) ? result[0] : result;
  return loc ? { uri: loc.uri, range: loc.range } : null;
}

export async function findReferences(
  client: LspClient,
  filePath: string,
  content: string,
  line: number,
  character: number,
): Promise<Location[]> {
  const uri = fileUri(filePath);
  await openDocument(client, filePath, content);
  const result: any = await client.request('textDocument/references', {
    textDocument: { uri },
    position: { line, character },
    context: { includeDeclaration: true },
  });
  await closeDocument(client, filePath);
  return (result ?? []).map((loc: any) => ({ uri: loc.uri, range: loc.range }));
}
