"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createGitRouter = void 0;
const express_1 = require("express");
const index_core_1 = require("../index-core");
const CommitMessageGenerator_1 = require("../services/CommitMessageGenerator");
const LocalGitService_1 = require("../services/LocalGitService");
const branchNames_1 = require("../utils/branchNames");
const log = (0, index_core_1.createLogger)('GitRoutes');
const createGitRouter = (sessionService, projectPath, options) => {
    const router = (0, express_1.Router)();
    const gitService = new LocalGitService_1.LocalGitService();
    const isGitEnabled = options?.isGitEnabled ?? true;
    router.use((req, res, next) => {
        if (!req.path.startsWith('/git/')) {
            next();
            return;
        }
        if (!isGitEnabled) {
            res.status(403).json({
                error: 'Git features are disabled for this session',
            });
            return;
        }
        next();
    });
    // Git session status endpoint
    router.get('/git/status', async (req, res) => {
        log.debug('[GitRoutes] GET /git/status');
        try {
            const status = await sessionService.getSessionStatus();
            res.json(status);
        }
        catch (error) {
            log.error('Failed to get git status:', error);
            res.status(500).json({
                error: 'Failed to get git status',
                details: error instanceof Error ? error.message : 'Unknown error',
            });
        }
    });
    // Publish changes endpoint (push branch and return PR URL)
    router.post('/git/publish', async (req, res) => {
        try {
            const result = await sessionService.publishChanges();
            log.info('Changes published successfully');
            res.json(result);
        }
        catch (error) {
            log.error('Failed to publish changes:', error);
            res.status(500).json({
                error: 'Failed to publish changes',
                details: error instanceof Error ? error.message : 'Unknown error',
            });
        }
    });
    // Current branch of the user's project
    router.get('/git/branch', async (req, res) => {
        try {
            const branch = await gitService.getCurrentBranch(projectPath);
            res.json({ branch });
        }
        catch (error) {
            log.warn('Failed to get current branch:', error);
            res.json({ branch: null });
        }
    });
    // Revert a single file to its state on main
    router.post('/git/revert-file', async (req, res) => {
        try {
            const { filePath } = req.body;
            if (!filePath || typeof filePath !== 'string') {
                return res.status(400).json({
                    error: 'Missing filePath',
                    details: 'filePath is required in the request body',
                });
            }
            await gitService.revertFile(projectPath, 'main', filePath);
            log.info(`Reverted file ${filePath} to main`);
            res.json({ success: true });
        }
        catch (error) {
            log.error('Failed to revert file:', error);
            res.status(500).json({
                error: 'Failed to revert file',
                details: error instanceof Error ? error.message : 'Unknown error',
            });
        }
    });
    // Undo last change endpoint
    router.post('/git/undo', async (req, res) => {
        try {
            await sessionService.undoLastChange();
            log.info('Successfully undid last change');
            res.json({ success: true });
        }
        catch (error) {
            log.error('Failed to undo last change:', error);
            res.status(500).json({
                error: 'Failed to undo last change',
                details: error instanceof Error ? error.message : 'Unknown error',
            });
        }
    });
    // Generate a commit message from the current diff using LLM
    router.get('/git/generate-commit-message', async (req, res) => {
        try {
            // Fetch diff and status in parallel to minimize subprocess wall time
            const [diff, gitStatus] = await Promise.all([
                gitService.getUncommittedDiff(projectPath),
                gitService.getStatus(projectPath),
            ]);
            if (!gitStatus.hasChanges) {
                return res.status(400).json({
                    error: 'No uncommitted changes',
                });
            }
            const message = await (0, CommitMessageGenerator_1.generateCommitMessage)({
                diff,
                instruction: 'Changes made with Rivet Visual Editor',
                filesChanged: gitStatus.files,
            });
            res.json({ message });
        }
        catch (error) {
            log.error('Failed to generate commit message:', error);
            res.status(500).json({
                error: 'Failed to generate commit message',
                details: error instanceof Error ? error.message : 'Unknown error',
            });
        }
    });
    // Commit staged changes with a user-provided message
    router.post('/git/commit', async (req, res) => {
        const { message, push } = req.body;
        if (!message || typeof message !== 'string' || !message.trim()) {
            return res.status(400).json({
                error: 'Commit message is required',
            });
        }
        let sha;
        try {
            sha = await gitService.commitWithMessage(projectPath, message.trim());
            log.info(`Committed with SHA: ${sha}`);
        }
        catch (error) {
            log.error('Failed to commit:', error);
            return res.status(500).json({
                error: 'Failed to commit',
                details: error instanceof Error ? error.message : 'Unknown error',
            });
        }
        if (push) {
            try {
                const branch = await gitService.getCurrentBranch(projectPath);
                await gitService.pushBranch(projectPath, branch);
                log.info(`Pushed branch: ${branch}`);
            }
            catch (error) {
                log.error('Failed to push after commit:', error);
                return res.status(500).json({
                    error: 'Commit succeeded but push failed',
                    sha,
                    pushed: false,
                    details: error instanceof Error ? error.message : 'Unknown error',
                });
            }
        }
        res.json({ sha, pushed: !!push });
    });
    // Push the current branch to origin
    router.post('/git/push', async (req, res) => {
        try {
            const branch = await gitService.getCurrentBranch(projectPath);
            await gitService.pushBranch(projectPath, branch);
            log.info(`Pushed branch: ${branch}`);
            res.json({ success: true, branch });
        }
        catch (error) {
            log.error('Failed to push:', error);
            res.status(500).json({
                error: 'Failed to push',
                details: error instanceof Error ? error.message : 'Unknown error',
            });
        }
    });
    // Generate a unique branch name candidate
    router.get('/git/generate-branch-name', async (req, res) => {
        try {
            const MAX_ATTEMPTS = 10;
            let branchName = null;
            for (let attempt = 0; attempt < MAX_ATTEMPTS; attempt++) {
                const candidate = (0, branchNames_1.generateBranchName)();
                const isTaken = await gitService.branchExists(projectPath, candidate);
                if (!isTaken) {
                    branchName = candidate;
                    break;
                }
                log.info(`Branch ${candidate} already exists, regenerating...`);
            }
            if (!branchName) {
                return res.status(500).json({
                    error: 'Failed to generate unique branch name',
                    details: `Could not find a unique name after ${MAX_ATTEMPTS} attempts`,
                });
            }
            res.json({ branchName });
        }
        catch (error) {
            log.error('Failed to generate branch name:', error);
            res.status(500).json({
                error: 'Failed to generate branch name',
                details: error instanceof Error ? error.message : 'Unknown error',
            });
        }
    });
    // Create and checkout a new branch
    router.post('/git/create-branch', async (req, res) => {
        try {
            const { branchName } = req.body;
            if (!branchName || typeof branchName !== 'string' || !branchName.trim()) {
                return res.status(400).json({
                    error: 'Branch name is required',
                });
            }
            const parentBranch = await gitService.createBranch(projectPath, branchName.trim());
            await sessionService.switchBranch(branchName.trim(), parentBranch);
            log.info(`Created branch: ${branchName} from ${parentBranch}`);
            res.json({ success: true, branchName: branchName.trim(), parentBranch });
        }
        catch (error) {
            log.error('Failed to create branch:', error);
            res.status(500).json({
                error: 'Failed to create branch',
                details: error instanceof Error ? error.message : 'Unknown error',
            });
        }
    });
    // List all local branches
    router.get('/git/branches', async (req, res) => {
        try {
            const branches = await sessionService.listBranches();
            res.json({ branches });
        }
        catch (error) {
            log.error('Failed to list branches:', error);
            res.status(500).json({
                error: 'Failed to list branches',
                details: error instanceof Error ? error.message : 'Unknown error',
            });
        }
    });
    // Switch to an existing branch
    router.post('/git/switch-branch', async (req, res) => {
        try {
            const { branchName } = req.body;
            if (!branchName || typeof branchName !== 'string' || !branchName.trim()) {
                return res.status(400).json({
                    error: 'Branch name is required',
                });
            }
            await sessionService.switchToBranch(branchName.trim());
            log.info(`Successfully switched to branch: ${branchName}`);
            res.json({ success: true, branchName: branchName.trim() });
        }
        catch (error) {
            log.error('Failed to switch branch:', error);
            res.status(500).json({
                error: 'Failed to switch branch',
                details: error instanceof Error ? error.message : 'Unknown error',
            });
        }
    });
    return router;
};
exports.createGitRouter = createGitRouter;
//# sourceMappingURL=git.js.map