/*
 * Copyright 2026, Jaime Terrats.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import { execFile as execFileCb } from 'node:child_process';
import { existsSync } from 'node:fs';
import { join, resolve, normalize } from 'node:path';
import { promisify } from 'node:util';
import { Hono } from 'hono';
import { getWorkspaceCwd } from '../middleware/workspace.js';
const execFile = promisify(execFileCb);
const EXEC_TIMEOUT = 10_000;
function statusLabel(code) {
    switch (code.trim()) {
        case 'M':
        case 'MM':
        case 'AM':
            return 'modified';
        case 'A':
            return 'added';
        case 'D':
            return 'deleted';
        case 'R':
            return 'renamed';
        case '??':
            return 'untracked';
        default:
            return 'unknown';
    }
}
function parseStatusLine(line) {
    if (!line || line.length < 4)
        return null;
    const status = line.slice(0, 2).trim() || line.slice(0, 2);
    const filePath = line.slice(3);
    if (!filePath)
        return null;
    return { status: status.trim() || '??', path: filePath, label: statusLabel(status) };
}
function isGitRepo(workspace) {
    return existsSync(join(workspace, '.git'));
}
function isPathSafe(workspace, filePath) {
    if (filePath.includes('..'))
        return false;
    const resolvedWorkspace = resolve(workspace);
    const resolved = resolve(resolvedWorkspace, normalize(filePath));
    return resolved.startsWith(resolvedWorkspace);
}
export function gitRoute(cwd) {
    const app = new Hono();
    app.get('/status', async (c) => {
        const workspace = getWorkspaceCwd(c, cwd);
        if (!isGitRepo(workspace)) {
            return c.json({ error: 'Not a git repository', files: [] }, 404);
        }
        try {
            const { stdout } = await execFile('git', ['status', '--porcelain'], {
                cwd: workspace,
                timeout: EXEC_TIMEOUT,
            });
            const files = stdout
                .split('\n')
                .map(parseStatusLine)
                .filter((f) => f !== null);
            return c.json({ files });
        }
        catch (err) {
            const message = err instanceof Error ? err.message : 'Unknown error';
            return c.json({ error: `Failed to get git status: ${message}` }, 500);
        }
    });
    app.get('/diff', async (c) => {
        const workspace = getWorkspaceCwd(c, cwd);
        if (!isGitRepo(workspace)) {
            return c.json({ error: 'Not a git repository', diff: '' }, 404);
        }
        const file = c.req.query('file');
        if (file && !isPathSafe(workspace, file)) {
            return c.json({ error: 'Invalid file path' }, 400);
        }
        try {
            const args = ['diff'];
            if (file) {
                args.push('--', file);
            }
            const { stdout } = await execFile('git', args, {
                cwd: workspace,
                timeout: EXEC_TIMEOUT,
                maxBuffer: 1024 * 1024 * 5, // 5MB
            });
            // If diff is empty, try --cached (staged changes)
            if (!stdout && file) {
                const { stdout: cachedDiff } = await execFile('git', ['diff', '--cached', '--', file], {
                    cwd: workspace,
                    timeout: EXEC_TIMEOUT,
                    maxBuffer: 1024 * 1024 * 5,
                });
                return c.json({ diff: cachedDiff, cached: true });
            }
            return c.json({ diff: stdout, cached: false });
        }
        catch (err) {
            const message = err instanceof Error ? err.message : 'Unknown error';
            return c.json({ error: `Failed to get diff: ${message}` }, 500);
        }
    });
    return app;
}
//# sourceMappingURL=git.js.map