import express from 'express';
import fs from 'fs';
import path from 'path';
import { execSync } from 'child_process';
import git from 'isomorphic-git';
import http from 'isomorphic-git/http/node';
import {
  isClientReady,
  createSession,
  sendPrompt,
  deleteSession,
  extractTextFromParts,
} from '../services/aiService.js';

const router = express.Router();

function getGitDir(dir) {
  return path.join(dir, '.git');
}

async function ensureGitRepo(dir) {
  const gitdir = getGitDir(dir);
  try {
    await fs.promises.access(gitdir);
    return { exists: true, gitdir };
  } catch {
    return { exists: false, gitdir };
  }
}

router.get('/status', async (req, res) => {
  try {
    const { dir } = req.query;
    if (!dir) {
      return res.status(400).json({ error: 'dir query parameter is required' });
    }

    const projectDir = path.resolve(dir);
    const { exists, gitdir } = await ensureGitRepo(projectDir);

    if (!exists) {
      return res.json({
        repoExists: false,
        branch: null,
        staged: [],
        unstaged: [],
        untracked: [],
      });
    }

    const statusMatrix = await git.statusMatrix({ fs, dir: projectDir, gitdir });
    const currentBranch = await git.currentBranch({ fs, dir: projectDir, gitdir }).catch(() => 'unknown');

    const staged = [];
    const unstaged = [];
    const untracked = [];

    for (const [filepath, head, workdir, stage] of statusMatrix) {
      if (head === 0 && workdir === 2 && stage === 0) {
        untracked.push({ path: filepath, status: 'U' });
        continue;
      }

      if (head === 0 && workdir === 2 && stage === 2) {
        staged.push({ path: filepath, status: 'A' });
        continue;
      }

      if (head === 1 && workdir === 2 && stage === 1) {
        unstaged.push({ path: filepath, status: 'M' });
        continue;
      }

      if (head === 1 && workdir === 2 && stage === 2) {
        staged.push({ path: filepath, status: 'M' });
        continue;
      }

      if (head === 1 && workdir === 2 && stage === 3) {
        staged.push({ path: filepath, status: 'M' });
        unstaged.push({ path: filepath, status: 'M' });
        continue;
      }

      if (head === 1 && stage === 0) {
        staged.push({ path: filepath, status: 'D' });
        continue;
      }

      if (head === 1 && workdir === 0 && stage === 1) {
        unstaged.push({ path: filepath, status: 'D' });
        continue;
      }
    }

    res.json({
      repoExists: true,
      branch: currentBranch,
      staged,
      unstaged,
      untracked,
    });
  } catch (err) {
    console.error('[Git] status error:', err);
    res.status(500).json({ error: err.message });
  }
});

router.post('/add', async (req, res) => {
  try {
    const { dir, filepath } = req.body;
    if (!dir || !filepath) {
      return res.status(400).json({ error: 'dir and filepath are required' });
    }

    const projectDir = path.resolve(dir);
    const { exists, gitdir } = await ensureGitRepo(projectDir);

    if (!exists) {
      return res.status(400).json({ error: 'Not a git repository' });
    }
    const absPath = path.resolve(projectDir, filepath);
    const fileExists = fs.existsSync(absPath);

    if (fileExists) {
      await git.add({ fs, dir: projectDir, gitdir, filepath });
    } else {
      await git.remove({ fs, dir: projectDir, gitdir, filepath });
    }

    res.json({ success: true });
  } catch (err) {
    console.error('[Git] add error:', err);
    res.status(500).json({ error: err.message });
  }
});

router.post('/unstage', async (req, res) => {
  try {
    const { dir, filepath } = req.body;
    if (!dir || !filepath) {
      return res.status(400).json({ error: 'dir and filepath are required' });
    }

    const projectDir = path.resolve(dir);
    const { exists, gitdir } = await ensureGitRepo(projectDir);

    if (!exists) {
      return res.status(400).json({ error: 'Not a git repository' });
    }

    await git.resetIndex({ fs, dir: projectDir, gitdir, filepath });

    res.json({ success: true });
  } catch (err) {
    console.error('[Git] unstage error:', err);
    res.status(500).json({ error: err.message });
  }
});

router.post('/commit', async (req, res) => {
  try {
    const { dir, message } = req.body;
    if (!dir || !message) {
      return res.status(400).json({ error: 'dir and message are required' });
    }

    const projectDir = path.resolve(dir);
    const { exists, gitdir } = await ensureGitRepo(projectDir);

    if (!exists) {
      return res.status(400).json({ error: 'Not a git repository' });
    }

    const sha = await git.commit({
      fs,
      dir: projectDir,
      gitdir,
      message,
      author: {
        name: process.env.GIT_AUTHOR_NAME || 'CodeFree-O',
        email: process.env.GIT_AUTHOR_EMAIL || 'codefree-o@local',
      },
    });

    res.json({ success: true, sha });
  } catch (err) {
    console.error('[Git] commit error:', err);
    res.status(500).json({ error: err.message });
  }
});

router.post('/discard', async (req, res) => {
  try {
    const { dir, filepath } = req.body;
    if (!dir || !filepath) {
      return res.status(400).json({ error: 'dir and filepath are required' });
    }

    const projectDir = path.resolve(dir);
    const { exists, gitdir } = await ensureGitRepo(projectDir);

    if (!exists) {
      return res.status(400).json({ error: 'Not a git repository' });
    }

    await git.checkout({ fs, dir: projectDir, gitdir, filepaths: [filepath], force: true });

    res.json({ success: true });
  } catch (err) {
    console.error('[Git] discard error:', err);
    res.status(500).json({ error: err.message });
  }
});

router.get('/diff', async (req, res) => {
  try {
    const { dir, filepath, cached } = req.query;
    if (!dir || !filepath) {
      return res.status(400).json({ error: 'dir and filepath are required' });
    }

    const projectDir = path.resolve(dir);
    const { exists, gitdir } = await ensureGitRepo(projectDir);

    if (!exists) {
      return res.status(400).json({ error: 'Not a git repository' });
    }

    const escapedFile = String(filepath).replace(/"/g, '\\"');
    const cachedFlag = cached === '1' || cached === 'true' ? '--cached' : '';
    const diff = execSync(`git diff ${cachedFlag} -- "${escapedFile}"`, {
      cwd: projectDir,
      encoding: 'utf-8',
      maxBuffer: 10 * 1024 * 1024,
      stdio: ['pipe', 'pipe', 'pipe'],
    });

    res.json({ diff });
  } catch (err) {
    console.error('[Git] diff error:', err);
    res.status(500).json({ error: err.message });
  }
});

router.get('/log', async (req, res) => {
  try {
    const { dir, depth } = req.query;
    if (!dir) {
      return res.status(400).json({ error: 'dir query parameter is required' });
    }

    const projectDir = path.resolve(dir);
    const { exists, gitdir } = await ensureGitRepo(projectDir);

    if (!exists) {
      return res.json({ commits: [] });
    }

    const commits = await git.log({ fs, dir: projectDir, gitdir, depth: parseInt(depth) || 50 });

    const branchHeads = {};
    try {
      const branches = await git.listBranches({ fs, dir: projectDir, gitdir });
      for (const branch of branches) {
        try {
          const ref = await git.resolveRef({ fs, dir: projectDir, gitdir, ref: branch });
          if (!branchHeads[ref]) branchHeads[ref] = [];
          branchHeads[ref].push(branch);
        } catch {}
      }
    } catch {}

    // Build graph structure for lane visualization
    const graph = commits.map((c) => ({
      oid: c.oid,
      parents: c.commit.parent || [],
      children: [], // { oid, parentIndex } - parentIndex indicates which parent this node is of the child
    }));

    // Build children links with parent index info
    // parentIndex = 0 means this node is the child's first parent (main line)
    // parentIndex > 0 means this node is a subsequent parent (merged branch)
    for (let i = 0; i < graph.length; i++) {
      for (let pi = 0; pi < graph[i].parents.length; pi++) {
        const p = graph[i].parents[pi];
        const parentNode = graph.find((n) => n.oid === p);
        if (parentNode) {
          parentNode.children.push({ oid: graph[i].oid, parentIndex: pi });
        }
      }
    }

    // Assign lanes using a proper topological algorithm
    // Process commits from oldest to newest so parent lanes are always known.
    // Key rules:
    //   1. Regular commits (1 parent) inherit the parent's lane — BUT only if
    //      no other child of the same parent has already claimed it. This keeps
    //      linear chains on a straight line while branching children get new lanes.
    //   2. Merge commits stay on the first-parent's lane (the "main line").
    //      Other parents' lanes become free after the merge point.
    //   3. Root commits get a fresh lane.
    //   4. Lanes that are freed by merges are reused for new branches.

    // Topological sort: parents before children (oldest first)
    const oidIndex = new Map(graph.map((n, i) => [n.oid, i]));
    const processed = new Set();
    const sorted = [];

    function addParentsFirst(idx) {
      if (processed.has(idx)) return;
      const node = graph[idx];
      for (const p of node.parents) {
        const pi = oidIndex.get(p);
        if (pi !== undefined) addParentsFirst(pi);
      }
      processed.add(idx);
      sorted.push(node);
    }
    for (let i = 0; i < graph.length; i++) {
      addParentsFirst(i);
    }

    const commitLane = new Map();
    const laneOccupant = new Map(); // lane → current commit occupying it
    const freeLanes = [];
    let nextLane = 0;

    function allocLane() {
      if (freeLanes.length > 0) return freeLanes.shift();
      return nextLane++;
    }

    function releaseLane(lane) {
      freeLanes.push(lane);
    }

    for (const node of sorted) {
      const numParents = node.parents.length;

      if (numParents === 0) {
        // Root commit (no parents)
        const lane = allocLane();
        commitLane.set(node.oid, lane);
        laneOccupant.set(lane, node.oid);
      } else if (numParents === 1) {
        const parentOid = node.parents[0];
        const parentLane = commitLane.get(parentOid);

        if (parentLane !== undefined && laneOccupant.get(parentLane) === parentOid) {
          // Parent's lane is still available — inherit it (linear continuation)
          commitLane.set(node.oid, parentLane);
          laneOccupant.set(parentLane, node.oid);
        } else {
          // Another child already took the parent's lane, or parent is unknown.
          // This is a branch point — allocate a fresh lane.
          const lane = allocLane();
          commitLane.set(node.oid, lane);
          laneOccupant.set(lane, node.oid);
        }
      } else {
        // Merge commit: stay on first-parent's lane; release merged-in lanes
        const firstLane = commitLane.get(node.parents[0]);
        const lane = firstLane ?? allocLane();
        commitLane.set(node.oid, lane);
        laneOccupant.set(lane, node.oid);

        // Free the lanes of merged-in branches so they can be reused
        for (let pi = 1; pi < node.parents.length; pi++) {
          const mergedLane = commitLane.get(node.parents[pi]);
          if (mergedLane !== undefined && mergedLane !== lane) {
            releaseLane(mergedLane);
          }
        }
      }
    }

    // Determine merge info for each commit
    const mergeInfo = graph.map((node) => {
      const isMerge = node.parents.length > 1;
      // Only count children with parentIndex === 0 as "branch" children.
      // Children with parentIndex > 0 are merge commits — being merged into
      // does not make this node a branch point.
      const isBranch = node.children.filter(c => c.parentIndex === 0).length > 1;
      const lane = commitLane.get(node.oid) ?? 0;
      const parentLanes = node.parents
        .map((p) => commitLane.get(p))
        .filter((l) => l !== undefined);
      const childLanes = node.children
        .map((c) => commitLane.get(c.oid))
        .filter((l) => l !== undefined);
      return {
        oid: node.oid,
        lane,
        isMerge,
        isBranch,
        parentLanes,
        childLanes,
      };
    });

    res.json({
      commits: commits.map((c) => ({
        oid: c.oid,
        parents: (c.commit.parent || []),
        message: c.commit.message,
        author: c.commit.author.name,
        email: c.commit.author.email,
        timestamp: c.commit.author.timestamp,
        branches: branchHeads[c.oid] || [],
      })),
      graph: mergeInfo,
    });
  } catch (err) {
    console.error('[Git] log error:', err);
    res.status(500).json({ error: err.message });
  }
});

router.get('/commit-files', async (req, res) => {
  try {
    const { dir, oid } = req.query;
    if (!dir || !oid) {
      return res.status(400).json({ error: 'dir and oid are required' });
    }

    const projectDir = path.resolve(dir);
    const { exists } = await ensureGitRepo(projectDir);

    if (!exists) {
      return res.status(400).json({ error: 'Not a git repository' });
    }

    const output = execSync(`git diff-tree --no-commit-id -r --name-status ${oid}`, {
      cwd: projectDir,
      encoding: 'utf-8',
      maxBuffer: 10 * 1024 * 1024,
    });

    const files = output
      .trim()
      .split('\n')
      .filter((line) => line.trim())
      .map((line) => {
        const parts = line.split('\t');
        return { status: parts[0], path: parts[1] };
      });

    res.json({ files });
  } catch (err) {
    console.error('[Git] commit-files error:', err);
    res.status(500).json({ error: err.message });
  }
});

router.get('/commit-diff', async (req, res) => {
  try {
    const { dir, oid, filepath } = req.query;
    if (!dir || !oid || !filepath) {
      return res.status(400).json({ error: 'dir, oid and filepath are required' });
    }

    const projectDir = path.resolve(dir);
    const { exists } = await ensureGitRepo(projectDir);

    if (!exists) {
      return res.status(400).json({ error: 'Not a git repository' });
    }

    let diff = '';
    const escapedFile = filepath.replace(/"/g, '\\"');

    try {
      diff = execSync(`git diff ${oid}~1..${oid} -- "${escapedFile}"`, {
        cwd: projectDir,
        encoding: 'utf-8',
        maxBuffer: 10 * 1024 * 1024,
        stdio: ['pipe', 'pipe', 'pipe'],
      });
    } catch (e) {
      console.log('[Git] commit-diff: oid~1..oid failed:', e.stderr?.toString().trim() || e.message);
      try {
        const showOutput = execSync(`git show ${oid} -- "${escapedFile}"`, {
          cwd: projectDir,
          encoding: 'utf-8',
          maxBuffer: 10 * 1024 * 1024,
          stdio: ['pipe', 'pipe', 'pipe'],
        });
        const diffIndex = showOutput.indexOf('diff --git');
        if (diffIndex >= 0) {
          diff = showOutput.substring(diffIndex);
        } else {
          diff = showOutput;
        }
      } catch (e2) {
        console.log('[Git] commit-diff: git show also failed:', e2.stderr?.toString().trim() || e2.message);
        diff = '';
      }
    }

    res.json({ diff });
  } catch (err) {
    console.error('[Git] commit-diff error:', err);
    res.status(500).json({ error: err.message });
  }
});

router.get('/tags', async (req, res) => {
  try {
    const { dir } = req.query;
    if (!dir) {
      return res.status(400).json({ error: 'dir query parameter is required' });
    }

    const projectDir = path.resolve(dir);
    const { exists, gitdir } = await ensureGitRepo(projectDir);

    if (!exists) {
      return res.json({ tags: [] });
    }

    const tags = await git.listTags({ fs, dir: projectDir, gitdir });

    res.json({ tags });
  } catch (err) {
    console.error('[Git] tags error:', err);
    res.status(500).json({ error: err.message });
  }
});

router.post('/checkout', async (req, res) => {
  try {
    const { dir, ref } = req.body;
    if (!dir || !ref) {
      return res.status(400).json({ error: 'dir and ref are required' });
    }

    const projectDir = path.resolve(dir);
    const { exists, gitdir } = await ensureGitRepo(projectDir);

    if (!exists) {
      return res.status(400).json({ error: 'Not a git repository' });
    }

    await git.checkout({ fs, dir: projectDir, gitdir, ref });

    res.json({ success: true });
  } catch (err) {
    console.error('[Git] checkout error:', err);
    res.status(500).json({ error: err.message });
  }
});

router.post('/branch', async (req, res) => {
  try {
    const { dir, name, ref } = req.body;
    if (!dir || !name) {
      return res.status(400).json({ error: 'dir and name are required' });
    }

    const projectDir = path.resolve(dir);
    const { exists, gitdir } = await ensureGitRepo(projectDir);

    if (!exists) {
      return res.status(400).json({ error: 'Not a git repository' });
    }

    await git.branch({ fs, dir: projectDir, gitdir, ref: name, object: ref || undefined });

    res.json({ success: true });
  } catch (err) {
    console.error('[Git] branch error:', err);
    res.status(500).json({ error: err.message });
  }
});

router.get('/branches', async (req, res) => {
  try {
    const { dir } = req.query;
    if (!dir) {
      return res.status(400).json({ error: 'dir query parameter is required' });
    }

    const projectDir = path.resolve(dir);
    const { exists, gitdir } = await ensureGitRepo(projectDir);

    if (!exists) {
      return res.json({ branches: [], current: null });
    }

    const branches = await git.listBranches({ fs, dir: projectDir, gitdir });
    const current = await git.currentBranch({ fs, dir: projectDir, gitdir }).catch(() => null);

    res.json({ branches, current });
  } catch (err) {
    console.error('[Git] branches error:', err);
    res.status(500).json({ error: err.message });
  }
});

router.post('/sync', async (req, res) => {
  try {
    const { dir, username, token } = req.body;
    if (!dir) {
      return res.status(400).json({ error: 'dir is required' });
    }

    const projectDir = path.resolve(dir);
    const { exists, gitdir } = await ensureGitRepo(projectDir);

    if (!exists) {
      return res.status(400).json({ error: 'Not a git repository' });
    }

    const currentBranch = await git.currentBranch({ fs, dir: projectDir, gitdir }).catch(() => null);
    if (!currentBranch) {
      return res.status(400).json({ error: '无法确定当前分支' });
    }

    const authUsername = username || process.env.GIT_USERNAME || '';
    const authPassword = token || process.env.GIT_TOKEN || process.env.GIT_PASSWORD || '';

    const onAuth = (authUsername && authPassword)
      ? () => ({ username: authUsername, password: authPassword })
      : undefined;

    const results = { fetch: null, pull: null, push: null };

    try {
      await git.fetch({
        fs, http, dir: projectDir, gitdir, remote: 'origin',
        ...(onAuth ? { onAuth } : {}),
      });
      results.fetch = 'ok';
    } catch (e) {
      results.fetch = e.message;
    }

    try {
      await git.pull({
        fs, http, dir: projectDir, gitdir, ref: currentBranch, remote: 'origin',
        author: {
          name: process.env.GIT_AUTHOR_NAME || 'CodeFree-O',
          email: process.env.GIT_AUTHOR_EMAIL || 'codefree-o@local',
        },
        ...(onAuth ? { onAuth } : {}),
      });
      results.pull = 'ok';
    } catch (e) {
      results.pull = e.message;
    }

    try {
      await git.push({
        fs, http, dir: projectDir, gitdir, remote: 'origin', ref: currentBranch,
        ...(onAuth ? { onAuth } : {}),
      });
      results.push = 'ok';
    } catch (e) {
      results.push = e.message;
    }

    const hasError = results.fetch !== 'ok' || results.pull !== 'ok' || results.push !== 'ok';
    if (hasError) {
      const errors = [];
      if (results.fetch !== 'ok') errors.push(`fetch: ${results.fetch}`);
      if (results.pull !== 'ok') errors.push(`pull: ${results.pull}`);
      if (results.push !== 'ok') errors.push(`push: ${results.push}`);
      return res.json({ success: false, results, error: errors.join('; ') });
    }

    res.json({ success: true, results });
  } catch (err) {
    console.error('[Git] sync error:', err);
    res.status(500).json({ error: err.message });
  }
});

router.post('/push', async (req, res) => {
  try {
    const { dir, username, token } = req.body;
    if (!dir) {
      return res.status(400).json({ error: 'dir is required' });
    }

    const projectDir = path.resolve(dir);
    const { exists, gitdir } = await ensureGitRepo(projectDir);

    if (!exists) {
      return res.status(400).json({ error: 'Not a git repository' });
    }
    
    const authUsername = username || process.env.GIT_USERNAME || '';
    const authPassword = token || process.env.GIT_TOKEN || process.env.GIT_PASSWORD || '';

    const pushOptions = {
      fs,
      http,
      dir: projectDir,
      gitdir,
      remote: 'origin',
      ref: 'master',
    };

    if (authUsername && authPassword) {
      pushOptions.onAuth = () => ({ username: authUsername, password: authPassword });
    }

    const result = await git.push(pushOptions);

    res.json({ success: true, pushResult: result });
  } catch (err) {
    console.error('[Git] push error:', err);
    res.status(500).json({ error: err.message });
  }
});

router.post('/generate-commit-message', async (req, res) => {
  try {
    const { dir } = req.body;

    if (!dir) {
      return res.status(400).json({ error: 'dir is required' });
    }

    if (!isClientReady()) {
      return res.status(503).json({ error: 'AI 服务尚未就绪，请稍后重试' });
    }

    const projectDir = path.resolve(dir);
    const { exists, gitdir } = await ensureGitRepo(projectDir);

    if (!exists) {
      return res.status(400).json({ error: 'Not a git repository' });
    }

    const statusMatrix = await git.statusMatrix({ fs, dir: projectDir, gitdir });
    const stagedFiles = [];

    for (const [filepath, head, workdir, stage] of statusMatrix) {
      if (
        (head === 0 && workdir === 2 && stage === 2) ||
        (head === 1 && workdir === 2 && stage === 2) ||
        (head === 1 && workdir === 2 && stage === 3) ||
        (head === 1 && stage === 0)
      ) {
        stagedFiles.push(filepath);
      }
    }

    if (stagedFiles.length === 0) {
      return res.status(400).json({ error: '没有暂存的文件可以生成提交信息' });
    }

    const diffs = [];
    for (const filepath of stagedFiles) {
      try {
        const diff = execSync(`git diff --cached -- "${filepath}"`, {
          cwd: projectDir,
          encoding: 'utf-8',
          maxBuffer: 10 * 1024 * 1024,
        });
        diffs.push({ file: filepath, diff });
      } catch (e) {
        diffs.push({ file: filepath, diff: `[无法获取差异: ${e.message}]` });
      }
    }

    const diffSummary = diffs
      .map((d) => `--- ${d.file} ---\n${d.diff}`)
      .join('\n\n');

    const prompt = `你是一个代码助手，请根据以下 Git diff 生成一条简洁的中文 git commit 提交信息。

要求：
- 使用中文
- 符合 conventional commits 规范（如 feat:, fix:, chore:, refactor:, docs:, style: 等）
- 一行概括核心变更，不超过72个字符
- 仅输出提交信息文本，不要解释

变更文件：
${diffs.map((d) => d.file).join('\n')}

Diff 内容：
${diffSummary}`;

    let sessionId = null;
    try {
      const session = await createSession('commit-msg-gen');
      sessionId = session.id;
      const parts = [{ type: 'text', text: prompt }]
      const result = await sendPrompt(sessionId, parts, {
        agent: 'summary',
      });
      const text = extractTextFromParts(result.parts || []);

      res.json({ message: text.trim() });
    } finally {
      if (sessionId) {
        try {
          await deleteSession(sessionId);
        } catch (e) {
          console.error('[Git] Failed to delete temp session:', e.message);
        }
      }
    }
  } catch (err) {
    console.error('[Git] generate-commit-message error:', err);
    res.status(500).json({ error: err.message });
  }
});

router.get('/conflict-status', async (req, res) => {
  try {
    const { dir } = req.query;
    if (!dir) {
      return res.status(400).json({ error: 'dir query parameter is required' });
    }

    const projectDir = path.resolve(dir);
    const { exists, gitdir } = await ensureGitRepo(projectDir);

    if (!exists) {
      return res.json({ hasConflicts: false, conflictedFiles: [], cleanFiles: [] });
    }

    const statusMatrix = await git.statusMatrix({ fs, dir: projectDir, gitdir });
    const conflictedFiles = [];
    const cleanFiles = [];

    for (const [filepath, head, workdir, stage] of statusMatrix) {
      if (stage === 2 && head !== 0) {
        const absPath = path.resolve(projectDir, filepath);
        try {
          const content = fs.readFileSync(absPath, 'utf-8');
          if (content.includes('<<<<<<<') && content.includes('=======') && content.includes('>>>>>>>')) {
            conflictedFiles.push({ path: filepath, status: 'U' });
            continue;
          }
        } catch {}
        cleanFiles.push({ path: filepath, status: 'M' });
      }
    }

    res.json({ hasConflicts: conflictedFiles.length > 0, conflictedFiles, cleanFiles });
  } catch (err) {
    console.error('[Git] conflict-status error:', err);
    res.status(500).json({ error: err.message });
  }
});

router.get('/conflict-file-content', async (req, res) => {
  try {
    const { dir, filepath } = req.query;
    if (!dir || !filepath) {
      return res.status(400).json({ error: 'dir and filepath are required' });
    }

    const projectDir = path.resolve(dir);
    const absPath = path.resolve(projectDir, filepath);

    try {
      const content = fs.readFileSync(absPath, 'utf-8');
      res.json({ content });
    } catch (e) {
      res.status(404).json({ error: 'File not found: ' + e.message });
    }
  } catch (err) {
    console.error('[Git] conflict-file-content error:', err);
    res.status(500).json({ error: err.message });
  }
});

router.post('/resolve-conflict', async (req, res) => {
  try {
    const { dir, filepath, content } = req.body;
    if (!dir || !filepath || content === undefined) {
      return res.status(400).json({ error: 'dir, filepath and content are required' });
    }

    const projectDir = path.resolve(dir);
    const { exists, gitdir } = await ensureGitRepo(projectDir);

    if (!exists) {
      return res.status(400).json({ error: 'Not a git repository' });
    }

    const absPath = path.resolve(projectDir, filepath);
    fs.writeFileSync(absPath, content, 'utf-8');

    await git.add({ fs, dir: projectDir, gitdir, filepath });

    res.json({ success: true });
  } catch (err) {
    console.error('[Git] resolve-conflict error:', err);
    res.status(500).json({ error: err.message });
  }
});

export { router as gitRouter };
