export function registerGitRoutes(app) {
  let gitLibraries = null;
  const getGitLibraries = async () => {
    if (!gitLibraries) {
      gitLibraries = await import('./index.js');
    }
    return gitLibraries;
  };

  app.get('/api/git/identities', async (req, res) => {
    const { getProfiles } = await getGitLibraries();
    try {
      const profiles = getProfiles();
      res.json(profiles);
    } catch (error) {
      console.error('Failed to list git identity profiles:', error);
      res.status(500).json({ error: 'Failed to list git identity profiles' });
    }
  });

  app.post('/api/git/identities', async (req, res) => {
    const { createProfile } = await getGitLibraries();
    try {
      const profile = createProfile(req.body);
      console.log(`Created git identity profile: ${profile.name} (${profile.id})`);
      res.json(profile);
    } catch (error) {
      console.error('Failed to create git identity profile:', error);
      res.status(400).json({ error: error.message || 'Failed to create git identity profile' });
    }
  });

  app.put('/api/git/identities/:id', async (req, res) => {
    const { updateProfile } = await getGitLibraries();
    try {
      const profile = updateProfile(req.params.id, req.body);
      console.log(`Updated git identity profile: ${profile.name} (${profile.id})`);
      res.json(profile);
    } catch (error) {
      console.error('Failed to update git identity profile:', error);
      res.status(400).json({ error: error.message || 'Failed to update git identity profile' });
    }
  });

  app.delete('/api/git/identities/:id', async (req, res) => {
    const { deleteProfile } = await getGitLibraries();
    try {
      deleteProfile(req.params.id);
      console.log(`Deleted git identity profile: ${req.params.id}`);
      res.json({ success: true });
    } catch (error) {
      console.error('Failed to delete git identity profile:', error);
      res.status(400).json({ error: error.message || 'Failed to delete git identity profile' });
    }
  });

  app.get('/api/git/global-identity', async (req, res) => {
    const { getGlobalIdentity } = await getGitLibraries();
    try {
      const identity = await getGlobalIdentity();
      res.json(identity);
    } catch (error) {
      console.error('Failed to get global git identity:', error);
      res.status(500).json({ error: 'Failed to get global git identity' });
    }
  });

  app.get('/api/git/discover-credentials', async (req, res) => {
    try {
      const { discoverGitCredentials } = await import('./index.js');
      const credentials = discoverGitCredentials();
      res.json(credentials);
    } catch (error) {
      console.error('Failed to discover git credentials:', error);
      res.status(500).json({ error: 'Failed to discover git credentials' });
    }
  });

  app.get('/api/git/check', async (req, res) => {
    const { isGitRepository } = await getGitLibraries();
    try {
      const directory = req.query.directory;
      if (!directory) {
        return res.status(400).json({ error: 'directory parameter is required' });
      }

      const isRepo = await isGitRepository(directory);
      res.json({ isGitRepository: isRepo });
    } catch (error) {
      console.error('Failed to check git repository:', error);
      res.status(500).json({ error: 'Failed to check git repository' });
    }
  });

  app.get('/api/git/remote-url', async (req, res) => {
    const { getRemoteUrl } = await getGitLibraries();
    try {
      const directory = req.query.directory;
      if (!directory) {
        return res.status(400).json({ error: 'directory parameter is required' });
      }
      const remote = req.query.remote || 'origin';

      const url = await getRemoteUrl(directory, remote);
      res.json({ url });
    } catch (error) {
      console.error('Failed to get remote url:', error);
      res.status(500).json({ error: 'Failed to get remote url' });
    }
  });

  app.get('/api/git/current-identity', async (req, res) => {
    const { getCurrentIdentity } = await getGitLibraries();
    try {
      const directory = req.query.directory;
      if (!directory) {
        return res.status(400).json({ error: 'directory parameter is required' });
      }

      const identity = await getCurrentIdentity(directory);
      res.json(identity);
    } catch (error) {
      console.error('Failed to get current git identity:', error);
      res.status(500).json({ error: 'Failed to get current git identity' });
    }
  });

  app.get('/api/git/has-local-identity', async (req, res) => {
    const { hasLocalIdentity } = await getGitLibraries();
    try {
      const directory = req.query.directory;
      if (!directory) {
        return res.status(400).json({ error: 'directory parameter is required' });
      }

      const hasLocal = await hasLocalIdentity(directory);
      res.json({ hasLocalIdentity: hasLocal });
    } catch (error) {
      console.error('Failed to check local git identity:', error);
      res.status(500).json({ error: 'Failed to check local git identity' });
    }
  });

  app.post('/api/git/set-identity', async (req, res) => {
    const { getProfile, setLocalIdentity, getGlobalIdentity } = await getGitLibraries();
    try {
      const directory = req.query.directory;
      if (!directory) {
        return res.status(400).json({ error: 'directory parameter is required' });
      }

      const { profileId } = req.body;
      if (!profileId) {
        return res.status(400).json({ error: 'profileId is required' });
      }

      let profile = null;

      if (profileId === 'global') {
        const globalIdentity = await getGlobalIdentity();
        if (!globalIdentity?.userName || !globalIdentity?.userEmail) {
          return res.status(404).json({ error: 'Global identity is not configured' });
        }
        profile = {
          id: 'global',
          name: 'Global Identity',
          userName: globalIdentity.userName,
          userEmail: globalIdentity.userEmail,
          sshKey: globalIdentity.sshCommand
            ? globalIdentity.sshCommand.replace('ssh -i ', '')
            : null,
        };
      } else {
        profile = getProfile(profileId);
        if (!profile) {
          return res.status(404).json({ error: 'Profile not found' });
        }
      }

      await setLocalIdentity(directory, profile);
      res.json({ success: true, profile });
    } catch (error) {
      console.error('Failed to set git identity:', error);
      res.status(500).json({ error: error.message || 'Failed to set git identity' });
    }
  });

  app.get('/api/git/status', async (req, res) => {
    const { getStatus, isGitRepository } = await getGitLibraries();

    const extractGitErrorText = (error) => {
      const message = typeof error?.message === 'string' ? error.message : '';
      const stderr = typeof error?.stderr === 'string' ? error.stderr : '';
      const stdout = typeof error?.stdout === 'string' ? error.stdout : '';
      return [message, stderr, stdout]
        .map((value) => String(value || '').trim())
        .filter(Boolean)
        .join('\n');
    };

    try {
      const directory = req.query.directory;
      if (!directory) {
        return res.status(400).json({ error: 'directory parameter is required' });
      }

      const isRepo = await isGitRepository(directory);
      if (!isRepo) {
        return res.json({ isGitRepository: false, files: [], branch: null, ahead: 0, behind: 0 });
      }

      const mode = req.query.mode === 'light' ? 'light' : undefined;
      const status = await getStatus(directory, { mode });
      res.json(status);
    } catch (error) {
      const errorText = extractGitErrorText(error);
      if (/not a git repository/i.test(errorText)) {
        return res.json({ isGitRepository: false, files: [], branch: null, ahead: 0, behind: 0 });
      }
      console.error('Failed to get git status:', error);
      res.status(500).json({ error: error.message || 'Failed to get git status' });
    }
  });

  app.get('/api/git/primary-root', async (req, res) => {
    const { resolvePrimaryWorktreeRoot } = await getGitLibraries();
    try {
      const directory = req.query.directory;
      if (!directory) {
        return res.status(400).json({ error: 'directory parameter is required' });
      }
      const result = await resolvePrimaryWorktreeRoot(directory);
      res.json(result);
    } catch (error) {
      console.error('Failed to resolve git primary root:', error);
      res.status(500).json({ error: error.message || 'Failed to resolve git primary root' });
    }
  });

  app.get('/api/git/toplevel', async (req, res) => {
    const { resolveWorktreeTopLevel } = await getGitLibraries();
    try {
      const directory = req.query.directory;
      if (!directory) {
        return res.status(400).json({ error: 'directory parameter is required' });
      }
      const result = await resolveWorktreeTopLevel(directory);
      res.json(result);
    } catch (error) {
      console.error('Failed to resolve git worktree toplevel:', error);
      res.status(500).json({ error: error.message || 'Failed to resolve git worktree toplevel' });
    }
  });

  app.post('/api/git/commit-summaries', async (req, res) => {
    const { getCommitSummaries } = await getGitLibraries();
    try {
      const directory = req.query.directory;
      if (!directory) {
        return res.status(400).json({ error: 'directory parameter is required' });
      }
      const result = await getCommitSummaries(directory, req.body?.shas);
      res.json(result);
    } catch (error) {
      console.error('Failed to get git commit summaries:', error);
      res.status(400).json({ error: error.message || 'Failed to get git commit summaries' });
    }
  });

  const handleIntegrateAction = (action, loadHandler) => {
    app.post(`/api/git/integrate/${action}`, async (req, res) => {
      try {
        const handler = await loadHandler();
        const result = await handler(req.body || {});
        res.json(result);
      } catch (error) {
        console.error(`Failed to run git integrate ${action}:`, error);
        res.status(400).json({ error: error.message || `Failed to run git integrate ${action}` });
      }
    });
  };

  handleIntegrateAction('plan', async () => {
    const { computeIntegratePlan } = await getGitLibraries();
    return (body) => computeIntegratePlan(body);
  });

  handleIntegrateAction('conflict-details', async () => {
    const { getIntegrateConflictDetails } = await getGitLibraries();
    return (body) => getIntegrateConflictDetails(body?.tempWorktreePath);
  });

  handleIntegrateAction('cherry-pick-status', async () => {
    const { isCherryPickInProgress } = await getGitLibraries();
    return (body) => isCherryPickInProgress(body?.tempWorktreePath);
  });

  handleIntegrateAction('run', async () => {
    const { integrateWorktreeCommits } = await getGitLibraries();
    return (body) => integrateWorktreeCommits(body?.plan);
  });

  handleIntegrateAction('abort', async () => {
    const { abortIntegrate } = await getGitLibraries();
    return (body) => abortIntegrate(body?.state);
  });

  handleIntegrateAction('continue', async () => {
    const { continueIntegrate } = await getGitLibraries();
    return (body) => continueIntegrate(body?.state);
  });

  app.get('/api/git/diff', async (req, res) => {
    const { getDiff } = await getGitLibraries();
    try {
      const directory = req.query.directory;
      if (!directory) {
        return res.status(400).json({ error: 'directory parameter is required' });
      }

      const path = req.query.path;
      if (!path || typeof path !== 'string') {
        return res.status(400).json({ error: 'path parameter is required' });
      }

      const staged = req.query.staged === 'true';
      const context = req.query.context ? parseInt(String(req.query.context), 10) : undefined;

      const diff = await getDiff(directory, {
        path,
        staged,
        contextLines: Number.isFinite(context) ? context : 3,
      });

      res.json({ diff });
    } catch (error) {
      console.error('Failed to get git diff:', error);
      res.status(500).json({ error: error.message || 'Failed to get git diff' });
    }
  });

  app.get('/api/git/file-diff', async (req, res) => {
    const { getFileDiff } = await getGitLibraries();
    try {
      const directory = req.query.directory;
      if (!directory || typeof directory !== 'string') {
        return res.status(400).json({ error: 'directory parameter is required' });
      }

      const pathParam = req.query.path;
      if (!pathParam || typeof pathParam !== 'string') {
        return res.status(400).json({ error: 'path parameter is required' });
      }

      const staged = req.query.staged === 'true';

      const result = await getFileDiff(directory, {
        path: pathParam,
        staged,
      });

      res.json({
        original: result.original,
        modified: result.modified,
        path: result.path,
        isBinary: Boolean(result.isBinary),
      });
    } catch (error) {
      console.error('Failed to get git file diff:', error);
      res.status(500).json({ error: error.message || 'Failed to get git file diff' });
    }
  });

  app.post('/api/git/revert', async (req, res) => {
    const { revertFile } = await getGitLibraries();
    try {
      const directory = req.query.directory;
      if (!directory) {
        return res.status(400).json({ error: 'directory parameter is required' });
      }

      const { path, scope } = req.body || {};
      if (!path || typeof path !== 'string') {
        return res.status(400).json({ error: 'path parameter is required' });
      }

      await revertFile(directory, path, { scope });
      res.json({ success: true });
    } catch (error) {
      console.error('Failed to revert git file:', error);
      res.status(500).json({ error: error.message || 'Failed to revert git file' });
    }
  });

  app.post('/api/git/stage', async (req, res) => {
    const { stageFiles } = await getGitLibraries();
    try {
      const directory = req.query.directory;
      if (!directory) {
        return res.status(400).json({ error: 'directory parameter is required' });
      }

      const { path, paths } = req.body || {};
      const filePaths = Array.isArray(paths) ? paths : [path];
      if (!filePaths.some((value) => typeof value === 'string' && value.trim())) {
        return res.status(400).json({ error: 'path parameter is required' });
      }

      await stageFiles(directory, filePaths);
      res.json({ success: true });
    } catch (error) {
      console.error('Failed to stage git file:', error);
      res.status(500).json({ error: error.message || 'Failed to stage git file' });
    }
  });

  app.post('/api/git/unstage', async (req, res) => {
    const { unstageFiles } = await getGitLibraries();
    try {
      const directory = req.query.directory;
      if (!directory) {
        return res.status(400).json({ error: 'directory parameter is required' });
      }

      const { path, paths } = req.body || {};
      const filePaths = Array.isArray(paths) ? paths : [path];
      if (!filePaths.some((value) => typeof value === 'string' && value.trim())) {
        return res.status(400).json({ error: 'path parameter is required' });
      }

      await unstageFiles(directory, filePaths);
      res.json({ success: true });
    } catch (error) {
      console.error('Failed to unstage git file:', error);
      res.status(500).json({ error: error.message || 'Failed to unstage git file' });
    }
  });

  app.post('/api/git/apply-hunk', async (req, res) => {
    const { applyHunk } = await getGitLibraries();
    try {
      const directory = req.query.directory;
      if (!directory) {
        return res.status(400).json({ error: 'directory parameter is required' });
      }

      const { path: filePath, patch, action } = req.body || {};
      if (!filePath || typeof filePath !== 'string') {
        return res.status(400).json({ error: 'path parameter is required' });
      }
      if (typeof patch !== 'string' || !patch.trim()) {
        return res.status(400).json({ error: 'patch is required' });
      }
      if (action !== 'stage' && action !== 'unstage' && action !== 'discard') {
        return res.status(400).json({ error: 'action must be stage, unstage, or discard' });
      }

      await applyHunk(directory, filePath, { patch, action });
      res.json({ success: true });
    } catch (error) {
      console.error('Failed to apply git hunk:', error);
      res.status(500).json({ error: error.message || 'Failed to apply git hunk' });
    }
  });

  app.post('/api/git/pull', async (req, res) => {
    const { pull } = await getGitLibraries();
    try {
      const directory = req.query.directory;
      if (!directory) {
        return res.status(400).json({ error: 'directory parameter is required' });
      }

      const result = await pull(directory, req.body);
      res.json(result);
    } catch (error) {
      console.error('Failed to pull:', error);
      res.status(500).json({ error: error.message || 'Failed to pull from remote' });
    }
  });

  app.post('/api/git/push', async (req, res) => {
    const { push } = await getGitLibraries();
    try {
      const directory = req.query.directory;
      if (!directory) {
        return res.status(400).json({ error: 'directory parameter is required' });
      }

      const result = await push(directory, req.body);
      res.json(result);
    } catch (error) {
      console.error('Failed to push:', error);
      res.status(500).json({ error: error.message || 'Failed to push to remote' });
    }
  });

  app.get('/api/git/stashes', async (req, res) => {
    const { listStashes } = await getGitLibraries();
    try {
      const directory = req.query.directory;
      if (!directory) return res.status(400).json({ error: 'directory parameter is required' });
      res.json({ stashes: await listStashes(directory) });
    } catch (error) {
      console.error('Failed to list stashes:', error);
      res.status(500).json({ error: error.message || 'Failed to list stashes' });
    }
  });

  app.post('/api/git/stashes/file-counts', async (req, res) => {
    const { countStashFiles } = await getGitLibraries();
    try {
      const directory = req.query.directory;
      if (!directory) return res.status(400).json({ error: 'directory parameter is required' });
      res.json({ counts: await countStashFiles(directory, req.body?.refs) });
    } catch (error) {
      console.error('Failed to count stash files:', error);
      res.status(500).json({ error: error.message || 'Failed to count stash files' });
    }
  });

  app.post('/api/git/stash', async (req, res) => {
    const { stashPush } = await getGitLibraries();
    try {
      const directory = req.query.directory;
      if (!directory) return res.status(400).json({ error: 'directory parameter is required' });
      res.json(await stashPush(directory, req.body));
    } catch (error) {
      console.error('Failed to stash changes:', error);
      res.status(500).json({ error: error.message || 'Failed to stash changes' });
    }
  });

  app.post('/api/git/stash/apply', async (req, res) => {
    const { stashApply } = await getGitLibraries();
    try {
      const directory = req.query.directory;
      if (!directory) return res.status(400).json({ error: 'directory parameter is required' });
      res.json(await stashApply(directory, req.body));
    } catch (error) {
      console.error('Failed to apply stash:', error);
      res.status(500).json({ error: error.message || 'Failed to apply stash' });
    }
  });

  app.post('/api/git/stash/pop', async (req, res) => {
    const { stashPop } = await getGitLibraries();
    try {
      const directory = req.query.directory;
      if (!directory) return res.status(400).json({ error: 'directory parameter is required' });
      res.json(await stashPop(directory, req.body));
    } catch (error) {
      console.error('Failed to pop stash:', error);
      res.status(500).json({ error: error.message || 'Failed to pop stash' });
    }
  });

  app.post('/api/git/stash/drop', async (req, res) => {
    const { stashDrop } = await getGitLibraries();
    try {
      const directory = req.query.directory;
      if (!directory) return res.status(400).json({ error: 'directory parameter is required' });
      res.json(await stashDrop(directory, req.body));
    } catch (error) {
      console.error('Failed to drop stash:', error);
      res.status(500).json({ error: error.message || 'Failed to drop stash' });
    }
  });

  app.post('/api/git/fetch', async (req, res) => {
    const { fetch: gitFetch } = await getGitLibraries();
    try {
      const directory = req.query.directory;
      if (!directory) {
        return res.status(400).json({ error: 'directory parameter is required' });
      }

      const result = await gitFetch(directory, req.body);
      res.json(result);
    } catch (error) {
      console.error('Failed to fetch:', error);
      res.status(500).json({ error: error.message || 'Failed to fetch from remote' });
    }
  });

  app.get('/api/git/remotes', async (req, res) => {
    const { getRemotes } = await getGitLibraries();
    try {
      const directory = req.query.directory;
      if (!directory) {
        return res.status(400).json({ error: 'directory parameter is required' });
      }

      const remotes = await getRemotes(directory);
      res.json(remotes);
    } catch (error) {
      console.error('Failed to get remotes:', error);
      res.status(500).json({ error: error.message || 'Failed to get remotes' });
    }
  });

  app.delete('/api/git/remotes', async (req, res) => {
    const { removeRemote } = await getGitLibraries();
    try {
      const directory = req.query.directory;
      if (!directory) {
        return res.status(400).json({ error: 'directory parameter is required' });
      }

      const remote = String(req.body?.remote || '').trim();
      if (!remote) {
        return res.status(400).json({ error: 'remote is required' });
      }

      const result = await removeRemote(directory, { remote });
      res.json(result);
    } catch (error) {
      console.error('Failed to remove remote:', error);
      res.status(500).json({ error: error.message || 'Failed to remove remote' });
    }
  });

  app.post('/api/git/rebase', async (req, res) => {
    const { rebase } = await getGitLibraries();
    try {
      const directory = req.query.directory;
      if (!directory) {
        return res.status(400).json({ error: 'directory parameter is required' });
      }

      const result = await rebase(directory, req.body);
      res.json(result);
    } catch (error) {
      console.error('Failed to rebase:', error);
      res.status(500).json({ error: error.message || 'Failed to rebase' });
    }
  });

  app.post('/api/git/rebase/abort', async (req, res) => {
    const { abortRebase } = await getGitLibraries();
    try {
      const directory = req.query.directory;
      if (!directory) {
        return res.status(400).json({ error: 'directory parameter is required' });
      }

      const result = await abortRebase(directory);
      res.json(result);
    } catch (error) {
      console.error('Failed to abort rebase:', error);
      res.status(500).json({ error: error.message || 'Failed to abort rebase' });
    }
  });

  app.post('/api/git/merge', async (req, res) => {
    const { merge } = await getGitLibraries();
    try {
      const directory = req.query.directory;
      if (!directory) {
        return res.status(400).json({ error: 'directory parameter is required' });
      }

      const result = await merge(directory, req.body);
      res.json(result);
    } catch (error) {
      console.error('Failed to merge:', error);
      res.status(500).json({ error: error.message || 'Failed to merge' });
    }
  });

  app.post('/api/git/merge/abort', async (req, res) => {
    const { abortMerge } = await getGitLibraries();
    try {
      const directory = req.query.directory;
      if (!directory) {
        return res.status(400).json({ error: 'directory parameter is required' });
      }

      const result = await abortMerge(directory);
      res.json(result);
    } catch (error) {
      console.error('Failed to abort merge:', error);
      res.status(500).json({ error: error.message || 'Failed to abort merge' });
    }
  });

  app.post('/api/git/rebase/continue', async (req, res) => {
    const { continueRebase } = await getGitLibraries();
    try {
      const directory = req.query.directory;
      if (!directory) {
        return res.status(400).json({ error: 'directory parameter is required' });
      }

      const result = await continueRebase(directory);
      res.json(result);
    } catch (error) {
      console.error('Failed to continue rebase:', error);
      res.status(500).json({ error: error.message || 'Failed to continue rebase' });
    }
  });

  app.post('/api/git/merge/continue', async (req, res) => {
    const { continueMerge } = await getGitLibraries();
    try {
      const directory = req.query.directory;
      if (!directory) {
        return res.status(400).json({ error: 'directory parameter is required' });
      }

      const result = await continueMerge(directory);
      res.json(result);
    } catch (error) {
      console.error('Failed to continue merge:', error);
      res.status(500).json({ error: error.message || 'Failed to continue merge' });
    }
  });

  app.get('/api/git/conflict-details', async (req, res) => {
    const { getConflictDetails } = await getGitLibraries();
    try {
      const directory = req.query.directory;
      if (!directory) {
        return res.status(400).json({ error: 'directory parameter is required' });
      }

      const result = await getConflictDetails(directory);
      res.json(result);
    } catch (error) {
      console.error('Failed to get conflict details:', error);
      res.status(500).json({ error: error.message || 'Failed to get conflict details' });
    }
  });

  app.post('/api/git/commit', async (req, res) => {
    const { commit } = await getGitLibraries();
    try {
      const directory = req.query.directory;
      if (!directory) {
        return res.status(400).json({ error: 'directory parameter is required' });
      }

      const { message, addAll, files, stageFiles } = req.body;
      if (!message) {
        return res.status(400).json({ error: 'message is required' });
      }

      const result = await commit(directory, message, {
        addAll,
        files,
        stageFiles,
      });
      res.json(result);
    } catch (error) {
      console.error('Failed to commit:', error);
      res.status(500).json({ error: error.message || 'Failed to create commit' });
    }
  });

  app.get('/api/git/branches', async (req, res) => {
    const { getBranches } = await getGitLibraries();
    try {
      const directory = req.query.directory;
      if (!directory) {
        return res.status(400).json({ error: 'directory parameter is required' });
      }

      const branches = await getBranches(directory);
      res.json(branches);
    } catch (error) {
      console.error('Failed to get branches:', error);
      res.status(500).json({ error: error.message || 'Failed to get branches' });
    }
  });

  app.post('/api/git/branches', async (req, res) => {
    const { createBranch } = await getGitLibraries();
    try {
      const directory = req.query.directory;
      if (!directory) {
        return res.status(400).json({ error: 'directory parameter is required' });
      }

      const { name, startPoint } = req.body;
      if (!name) {
        return res.status(400).json({ error: 'name is required' });
      }

      const result = await createBranch(directory, name, { startPoint });
      res.json(result);
    } catch (error) {
      console.error('Failed to create branch:', error);
      res.status(500).json({ error: error.message || 'Failed to create branch' });
    }
  });

  app.delete('/api/git/branches', async (req, res) => {
    const { deleteBranch } = await getGitLibraries();
    try {
      const directory = req.query.directory;
      if (!directory) {
        return res.status(400).json({ error: 'directory parameter is required' });
      }

      const { branch, force } = req.body;
      if (!branch) {
        return res.status(400).json({ error: 'branch is required' });
      }

      const result = await deleteBranch(directory, branch, { force });
      res.json(result);
    } catch (error) {
      console.error('Failed to delete branch:', error);
      res.status(500).json({ error: error.message || 'Failed to delete branch' });
    }
  });


  app.put('/api/git/branches/rename', async (req, res) => {
    const { renameBranch } = await getGitLibraries();
    try {
      const directory = req.query.directory;
      if (!directory) {
        return res.status(400).json({ error: 'directory parameter is required' });
      }

      const { oldName, newName } = req.body;
      if (!oldName) {
        return res.status(400).json({ error: 'oldName is required' });
      }
      if (!newName) {
        return res.status(400).json({ error: 'newName is required' });
      }

      const result = await renameBranch(directory, oldName, newName);
      res.json(result);
    } catch (error) {
      console.error('Failed to rename branch:', error);
      res.status(500).json({ error: error.message || 'Failed to rename branch' });
    }
  });
  app.delete('/api/git/remote-branches', async (req, res) => {
    const { deleteRemoteBranch } = await getGitLibraries();
    try {
      const directory = req.query.directory;
      if (!directory) {
        return res.status(400).json({ error: 'directory parameter is required' });
      }

      const { branch, remote } = req.body;
      if (!branch) {
        return res.status(400).json({ error: 'branch is required' });
      }

      const result = await deleteRemoteBranch(directory, { branch, remote });
      res.json(result);
    } catch (error) {
      console.error('Failed to delete remote branch:', error);
      res.status(500).json({ error: error.message || 'Failed to delete remote branch' });
    }
  });

  app.post('/api/git/checkout', async (req, res) => {
    const { checkoutBranch } = await getGitLibraries();
    try {
      const directory = req.query.directory;
      if (!directory) {
        return res.status(400).json({ error: 'directory parameter is required' });
      }

      const { branch } = req.body;
      if (!branch) {
        return res.status(400).json({ error: 'branch is required' });
      }

      const result = await checkoutBranch(directory, branch);
      res.json(result);
    } catch (error) {
      console.error('Failed to checkout branch:', error);
      res.status(500).json({ error: error.message || 'Failed to checkout branch' });
    }
  });

  app.post('/api/git/checkout-commit', async (req, res) => {
    const { checkoutCommit } = await getGitLibraries();
    try {
      const directory = req.query.directory;
      if (!directory) {
        return res.status(400).json({ error: 'directory parameter is required' });
      }
      const { hash } = req.body;
      if (!req.body.hash || typeof req.body.hash !== 'string' || !/^[0-9a-fA-F]{7,40}$/.test(req.body.hash)) {
        return res.status(400).json({ error: 'Invalid commit hash' });
      }
      const result = await checkoutCommit(directory, hash);
      res.json(result);
    } catch (error) {
      console.error('Failed to checkout commit:', error);
      res.status(500).json({ error: error.message || 'Failed to checkout commit' });
    }
  });

  app.post('/api/git/cherry-pick', async (req, res) => {
    const { cherryPick } = await getGitLibraries();
    try {
      const directory = req.query.directory;
      if (!directory) {
        return res.status(400).json({ error: 'directory parameter is required' });
      }
      const { hash } = req.body;
      if (!req.body.hash || typeof req.body.hash !== 'string' || !/^[0-9a-fA-F]{7,40}$/.test(req.body.hash)) {
        return res.status(400).json({ error: 'Invalid commit hash' });
      }
      const result = await cherryPick(directory, hash);
      res.json(result);
    } catch (error) {
      console.error('Failed to cherry-pick:', error);
      res.status(500).json({ error: error.message || 'Failed to cherry-pick' });
    }
  });

  app.post('/api/git/revert-commit', async (req, res) => {
    const { revertCommit } = await getGitLibraries();
    try {
      const directory = req.query.directory;
      if (!directory) {
        return res.status(400).json({ error: 'directory parameter is required' });
      }
      const { hash } = req.body;
      if (!req.body.hash || typeof req.body.hash !== 'string' || !/^[0-9a-fA-F]{7,40}$/.test(req.body.hash)) {
        return res.status(400).json({ error: 'Invalid commit hash' });
      }
      const result = await revertCommit(directory, hash);
      res.json(result);
    } catch (error) {
      console.error('Failed to revert commit:', error);
      res.status(500).json({ error: error.message || 'Failed to revert commit' });
    }
  });

  app.post('/api/git/reset-to-commit', async (req, res) => {
    const { resetToCommit } = await getGitLibraries();
    try {
      const directory = req.query.directory;
      if (!directory) {
        return res.status(400).json({ error: 'directory parameter is required' });
      }
      const { hash, mode, force } = req.body;
      if (!req.body.hash || typeof req.body.hash !== 'string' || !/^[0-9a-fA-F]{7,40}$/.test(req.body.hash)) {
        return res.status(400).json({ error: 'Invalid commit hash' });
      }
      if (!['soft', 'mixed', 'hard'].includes(mode)) {
        return res.status(400).json({ error: 'mode must be soft, mixed, or hard' });
      }
      const result = await resetToCommit(directory, hash, mode, force === true);
      res.json(result);
    } catch (error) {
      console.error('Failed to reset to commit:', error);
      res.status(500).json({ error: error.message || 'Failed to reset' });
    }
  });

  app.get('/api/git/worktrees', async (req, res) => {
    const { getWorktrees } = await getGitLibraries();
    try {
      const directory = req.query.directory;
      if (!directory) {
        return res.status(400).json({ error: 'directory parameter is required' });
      }

      const worktrees = await getWorktrees(directory);
      res.json(worktrees);
    } catch (error) {
      // Worktrees are an optional feature. Avoid repeated 500s (and repeated client retries)
      // when the directory isn't a git repo or uses shell shorthand like "~/".
      console.warn('Failed to get worktrees, returning empty list:', error?.message || error);
      res.setHeader('X-OpenChamber-Warning', 'git worktrees unavailable');
      res.json([]);
    }
  });

  app.post('/api/git/worktrees/validate', async (req, res) => {
    const { validateWorktreeCreate } = await getGitLibraries();
    if (typeof validateWorktreeCreate !== 'function') {
      return res.status(501).json({ error: 'Worktree validation is not available' });
    }

    try {
      const directory = req.query.directory;
      if (!directory || typeof directory !== 'string') {
        return res.status(400).json({ error: 'directory parameter is required' });
      }

      const result = await validateWorktreeCreate(directory, req.body || {});
      res.json(result);
    } catch (error) {
      console.error('Failed to validate worktree creation:', error);
      res.status(500).json({ error: error.message || 'Failed to validate worktree creation' });
    }
  });

  app.post('/api/git/worktrees', async (req, res) => {
    const { createWorktree } = await getGitLibraries();
    if (typeof createWorktree !== 'function') {
      return res.status(501).json({ error: 'Worktree creation is not available' });
    }

    try {
      const directory = req.query.directory;
      if (!directory || typeof directory !== 'string') {
        return res.status(400).json({ error: 'directory parameter is required' });
      }

      const created = await createWorktree(directory, req.body || {});
      res.json(created);
    } catch (error) {
      console.error('Failed to create worktree:', error);
      res.status(500).json({ error: error.message || 'Failed to create worktree' });
    }
  });

  app.post('/api/git/worktrees/preview', async (req, res) => {
    const { previewWorktreeCreate } = await getGitLibraries();
    if (typeof previewWorktreeCreate !== 'function') {
      return res.status(501).json({ error: 'Worktree preview is not available' });
    }

    try {
      const directory = req.query.directory;
      if (!directory || typeof directory !== 'string') {
        return res.status(400).json({ error: 'directory parameter is required' });
      }

      const preview = await previewWorktreeCreate(directory, req.body || {});
      res.json(preview);
    } catch (error) {
      console.error('Failed to preview worktree:', error);
      res.status(500).json({ error: error.message || 'Failed to preview worktree' });
    }
  });

  app.get('/api/git/worktrees/bootstrap-status', async (req, res) => {
    const { getWorktreeBootstrapStatus } = await getGitLibraries();
    if (typeof getWorktreeBootstrapStatus !== 'function') {
      return res.status(501).json({ error: 'Worktree bootstrap status is not available' });
    }

    try {
      const directory = req.query.directory;
      if (!directory || typeof directory !== 'string') {
        return res.status(400).json({ error: 'directory parameter is required' });
      }

      const status = await getWorktreeBootstrapStatus(directory);
      res.json(status);
    } catch (error) {
      console.error('Failed to get worktree bootstrap status:', error);
      res.status(500).json({ error: error.message || 'Failed to get worktree bootstrap status' });
    }
  });

  app.delete('/api/git/worktrees', async (req, res) => {
    const { removeWorktree } = await getGitLibraries();
    if (typeof removeWorktree !== 'function') {
      return res.status(501).json({ error: 'Worktree removal is not available' });
    }

    try {
      const directory = req.query.directory;
      if (!directory || typeof directory !== 'string') {
        return res.status(400).json({ error: 'directory parameter is required' });
      }

      const worktreeDirectory = typeof req.body?.directory === 'string' ? req.body.directory : '';
      if (!worktreeDirectory) {
        return res.status(400).json({ error: 'worktree directory is required' });
      }

      const result = await removeWorktree(directory, {
        directory: worktreeDirectory,
        deleteLocalBranch: req.body?.deleteLocalBranch === true,
      });
      res.json({ success: Boolean(result) });
    } catch (error) {
      console.error('Failed to remove worktree:', error);
      res.status(500).json({ error: error.message || 'Failed to remove worktree' });
    }
  });

  app.get('/api/git/worktree-type', async (req, res) => {
    const { isLinkedWorktree } = await getGitLibraries();
    try {
      const { directory } = req.query;
      if (!directory || typeof directory !== 'string') {
        return res.status(400).json({ error: 'directory parameter is required' });
      }
      const linked = await isLinkedWorktree(directory);
      res.json({ linked });
    } catch (error) {
      console.error('Failed to determine worktree type:', error);
      res.status(500).json({ error: error.message || 'Failed to determine worktree type' });
    }
  });

  app.post('/api/git/validate-directory', async (req, res) => {
    const { validateWorktreeDirectory } = await getGitLibraries();
    if (typeof validateWorktreeDirectory !== 'function') {
      return res.status(501).json({ error: 'validateWorktreeDirectory is not available' });
    }
    try {
      const { directory, worktreeRoot } = req.body || {};
      if (!directory || typeof directory !== 'string') {
        return res.status(400).json({ error: 'directory is required' });
      }
      if (!worktreeRoot || typeof worktreeRoot !== 'string') {
        return res.status(400).json({ error: 'worktreeRoot is required' });
      }
      const result = await validateWorktreeDirectory(directory, worktreeRoot);
      res.json(result);
    } catch (error) {
      console.error('Failed to validate worktree directory:', error);
      res.status(500).json({ error: error.message || 'Failed to validate worktree directory' });
    }
  });

  app.post('/api/git/canonicalize-worktree-state', async (req, res) => {
    const { canonicalizeWorktreeState } = await getGitLibraries();
    if (typeof canonicalizeWorktreeState !== 'function') {
      return res.status(501).json({ error: 'canonicalizeWorktreeState is not available' });
    }
    try {
      const { directory } = req.body || {};
      if (!directory || typeof directory !== 'string') {
        return res.status(400).json({ error: 'directory is required' });
      }
      const result = await canonicalizeWorktreeState(directory);
      res.json(result);
    } catch (error) {
      console.error('Failed to canonicalize worktree state:', error);
      res.status(500).json({ error: error.message || 'Failed to canonicalize worktree state' });
    }
  });

  app.get('/api/git/log', async (req, res) => {
    const { getLog } = await getGitLibraries();
    try {
      const directory = req.query.directory;
      if (!directory) {
        return res.status(400).json({ error: 'directory parameter is required' });
      }

      const { maxCount, from, to, file } = req.query;
      const all = req.query.all === 'true';
      const log = await getLog(directory, {
        maxCount: maxCount ? parseInt(maxCount) : undefined,
        from,
        to,
        file,
        all
      });
      res.json(log);
    } catch (error) {
      console.error('Failed to get log:', error);
      res.status(500).json({ error: error.message || 'Failed to get commit log' });
    }
  });

  app.get('/api/git/commit-files', async (req, res) => {
    const { getCommitFiles } = await getGitLibraries();
    try {
      const { directory, hash } = req.query;
      if (!directory) {
        return res.status(400).json({ error: 'directory parameter is required' });
      }
      if (!hash) {
        return res.status(400).json({ error: 'hash parameter is required' });
      }

      const result = await getCommitFiles(directory, hash);
      res.json(result);
    } catch (error) {
      console.error('Failed to get commit files:', error);
      res.status(500).json({ error: error.message || 'Failed to get commit files' });
    }
  });

  app.get('/api/git/commit-file-diff', async (req, res) => {
    const { getCommitFileDiff } = await getGitLibraries();
    try {
      const { directory, hash, path: filePath } = req.query;
      if (!directory || typeof directory !== 'string') {
        return res.status(400).json({ error: 'directory parameter is required' });
      }
      if (!hash || typeof hash !== 'string') {
        return res.status(400).json({ error: 'hash parameter is required' });
      }
      if (!/^[0-9a-fA-F]{7,40}$/.test(hash)) {
        return res.status(400).json({ error: 'hash must be a valid commit SHA' });
      }
      if (!filePath || typeof filePath !== 'string') {
        return res.status(400).json({ error: 'path parameter is required' });
      }

      const isBinary = req.query.binary === 'true';
      const result = await getCommitFileDiff(directory, hash, filePath, isBinary);
      res.json(result);
    } catch (error) {
      console.error('Failed to get commit file diff:', error);
      res.status(500).json({ error: error.message || 'Failed to get commit file diff' });
    }
  });

}
