/**
 * Edit tool — exact string replacement in files.
 */

import { readFileSync, writeFileSync, existsSync } from 'fs';
import { resolve, normalize } from 'path';

export const definition = {
  name: 'Edit',
  description: 'Edit a file by performing exact string replacement. The old_string must be unique in the file unless replace_all is true. You must Read a file before editing it.',
  input_schema: {
    type: 'object',
    properties: {
      file_path: { type: 'string', description: 'Absolute path to the file to modify' },
      old_string: { type: 'string', description: 'The exact text to replace (must be unique in the file)' },
      new_string: { type: 'string', description: 'The replacement text' },
      replace_all: { type: 'boolean', description: 'Replace all occurrences (default false)', default: false }
    },
    required: ['file_path', 'old_string', 'new_string']
  }
};

export async function execute(input, context) {
  const { file_path, old_string, new_string, replace_all } = input;

  if (!file_path) return { content: 'Error: file_path is required', is_error: true };
  if (old_string === undefined) return { content: 'Error: old_string is required', is_error: true };
  if (new_string === undefined) return { content: 'Error: new_string is required', is_error: true };
  if (old_string === new_string) return { content: 'Error: old_string and new_string are identical', is_error: true };

  const resolved = resolve(normalize(file_path));
  const wsNorm = resolve(normalize(context.workspaceRoot));

  if (!resolved.startsWith(wsNorm)) {
    return { content: `Error: Edit is restricted to workspace: ${context.workspaceRoot}`, is_error: true };
  }

  if (!existsSync(resolved)) {
    return { content: `Error: File not found: ${resolved}`, is_error: true };
  }

  // Safety: must have been Read first
  if (context.readFileTimestamps && !context.readFileTimestamps[resolved]) {
    return { content: `Error: File "${resolved}" has not been Read in this session. Read it first.`, is_error: true };
  }

  try {
    const content = readFileSync(resolved, 'utf-8');
    const occurrences = content.split(old_string).length - 1;

    if (occurrences === 0) {
      // Show a snippet of the file for context
      const preview = content.slice(0, 200).replace(/\n/g, '\\n');
      return { content: `Error: old_string not found in file. File starts with: "${preview}..."`, is_error: true };
    }

    if (occurrences > 1 && !replace_all) {
      return {
        content: `Error: old_string found ${occurrences} times. Use replace_all: true to replace all, or provide more context to make it unique.`,
        is_error: true
      };
    }

    let updated;
    if (replace_all) {
      updated = content.split(old_string).join(new_string);
    } else {
      const idx = content.indexOf(old_string);
      updated = content.slice(0, idx) + new_string + content.slice(idx + old_string.length);
    }

    writeFileSync(resolved, updated, 'utf-8');

    // Show context around the edit
    const editIdx = updated.indexOf(new_string);
    const start = Math.max(0, editIdx - 50);
    const end = Math.min(updated.length, editIdx + new_string.length + 50);
    const snippet = updated.slice(start, end);
    const lineNum = updated.slice(0, editIdx).split('\n').length;

    const count = replace_all ? `${occurrences} occurrence(s)` : '1 occurrence';
    return {
      content: `Replaced ${count} in ${resolved} (around line ${lineNum}):\n...${snippet}...`,
      is_error: false
    };
  } catch (err) {
    return { content: `Error editing file: ${err.message}`, is_error: true };
  }
}
