'use strict';

const fs = require('fs');
const path = require('path');
const { structuredPatch } = require('diff');
const { getContainerContext, resolveContainerPath, execContainerAction } = require('./container_bridge');

function resolvePath(workspace, p) {
  if (path.isAbsolute(p)) return p;
  return path.join(workspace, p);
}

function diffSummary(oldText, newText) {
  const patch = structuredPatch('old', 'new', oldText, newText, '', '', { context: 1 });
  let added = 0;
  let removed = 0;
  const hunks = patch.hunks.map((hunk) => {
    let oldLine = hunk.oldStart;
    let newLine = hunk.newStart;
    const lines = hunk.lines.map((line) => {
      const prefix = line[0];
      const content = line.slice(1);
      let lineNum = null;
      if (prefix === ' ') {
        lineNum = oldLine;
        oldLine += 1;
        newLine += 1;
      } else if (prefix === '-') {
        lineNum = oldLine;
        removed += 1;
        oldLine += 1;
      } else if (prefix === '+') {
        lineNum = newLine;
        added += 1;
        newLine += 1;
      }
      return { prefix, lineNum, content };
    });
    return lines;
  });
  return { added, removed, hunks };
}

function countLines(text) {
  if (!text) return 0;
  return String(text).split(/\r?\n/).length;
}

function findMatchLineNumbers(content, target) {
  if (!target) return [];
  const lines = [];
  let start = 0;
  while (true) {
    const idx = content.indexOf(target, start);
    if (idx === -1) break;
    const lineNo = content.slice(0, idx).split(/\r?\n/).length;
    lines.push(lineNo);
    start = idx + Math.max(1, target.length);
  }
  return lines;
}

function editFileTool(workspace, args) {
  const target = resolvePath(workspace, args.file_path);
  const oldString = args.old_string ?? '';
  const newString = args.new_string ?? '';
  if (!Object.prototype.hasOwnProperty.call(args || {}, 'replace_all')) {
    return { success: false, error: '缺少必要参数: replace_all（必须显式传入 true 或 false）' };
  }
  const replaceAll = args.replace_all;
  if (typeof replaceAll !== 'boolean') {
    return { success: false, error: 'replace_all 必须是 true 或 false' };
  }
  const shortOldStringNotice = countLines(oldString) < 3;
  const ctx = getContainerContext();
  if (ctx) {
    const resolved = resolveContainerPath(workspace, args.file_path || '.', ctx);
    if (resolved.error) return { success: false, error: resolved.error };
    const rel = resolved.relativePath;
    if (!oldString) return { success: false, error: 'old_string 不能为空，请从 read_file 内容中精确复制' };

    const readResp = execContainerAction(ctx, 'read_file', { path: rel });
    if (!readResp.success) return { success: false, error: readResp.error || '读取失败' };
    const original = readResp.content || '';
    if (!original.includes(oldString)) {
      return { success: false, error: 'old_string 未匹配到内容' };
    }
    const matchedLines = findMatchLineNumbers(original, oldString);
    const foundCount = matchedLines.length;
    const replacements = replaceAll ? (original.split(oldString).length - 1) : 1;
    const updated = replaceAll
      ? original.split(oldString).join(newString)
      : original.replace(oldString, newString);
    const writeResp = execContainerAction(ctx, 'write_file', {
      path: rel,
      content: updated,
      mode: 'w',
    });
    if (!writeResp.success) return { success: false, error: writeResp.error || '写入失败' };
    const diff = diffSummary(original, updated);
    const messageParts = [];
    if (shortOldStringNotice) {
      messageParts.push('提示：old_string 少于3行，已继续执行；需要批量替换的场景可以单行或不足一行');
    }
    if (foundCount > 1) {
      messageParts.push(`发现${foundCount}处，于${matchedLines.join(',')}行共替换${replacements}处`);
    }
    return {
      success: true,
      path: resolved.containerPath,
      replacements,
      found_matches: foundCount,
      matched_lines: matchedLines,
      message: messageParts.length > 0 ? messageParts.join('；') : undefined,
      diff,
    };
  }
  try {
    let creating = false;
    if (!fs.existsSync(target)) {
      creating = true;
      fs.mkdirSync(path.dirname(target), { recursive: true });
      fs.writeFileSync(target, '', 'utf8');
    }
    const stat = fs.statSync(target);
    if (!stat.isFile()) {
      return { success: false, error: '目标不是文件' };
    }
    const original = fs.readFileSync(target, 'utf8');
    if (oldString === '') {
      return { success: false, error: 'old_string 不能为空，请从 read_file 内容中精确复制' };
    }
    if (!creating && !original.includes(oldString)) {
      return { success: false, error: 'old_string 未匹配到内容' };
    }
    const matchedLines = creating ? [] : findMatchLineNumbers(original, oldString);
    const foundCount = matchedLines.length;
    const updated = creating
      ? newString
      : (replaceAll ? original.split(oldString).join(newString) : original.replace(oldString, newString));
    let replacements = creating ? 0 : (replaceAll ? (original.split(oldString).length - 1) : 1);
    if (creating && newString) replacements = 1;
    fs.writeFileSync(target, updated, 'utf8');
    const diff = diffSummary(original, updated);
    const messageParts = [];
    if (shortOldStringNotice) {
      messageParts.push('提示：old_string 少于3行，已继续执行；需要批量替换的场景可以单行或不足一行');
    }
    if (foundCount > 1) {
      messageParts.push(`发现${foundCount}处，于${matchedLines.join(',')}行共替换${replacements}处`);
    }
    return {
      success: true,
      path: target,
      replacements,
      found_matches: foundCount,
      matched_lines: matchedLines,
      message: messageParts.length > 0 ? messageParts.join('；') : undefined,
      diff,
    };
  } catch (err) {
    return { success: false, error: err.message || String(err) };
  }
}

module.exports = { editFileTool, resolvePath };
