import { specStore } from '../../storage/index.js';
import { ti } from '../../i18n/index.js';
import { git, resolveProjectPath, resolveBaseBranch } from './git-helpers.js';
export async function handleLinkCommits(projectId, specId) {
    const projectPath = await resolveProjectPath(projectId);
    const searchPattern = specId ?? 'SPEC-';
    const commits = [];
    const orphanCommits = [];
    try {
        const { stdout } = await git(projectPath, [
            'log',
            '--all',
            `--grep=${searchPattern}`,
            '--format=%H|%s|%an|%aI',
            '-100',
        ]);
        if (stdout.trim()) {
            const lines = stdout.trim().split('\n');
            for (const line of lines) {
                const [hash, message, author, date] = line.split('|');
                if (!hash || !message) {
                    continue;
                }
                const specMatch = message.match(/SPEC-\d{3}/g);
                const linkedSpecId = specMatch ? specMatch[0] : (specId ?? 'unknown');
                let filesChanged = [];
                try {
                    const { stdout: diffOut } = await git(projectPath, [
                        'diff-tree',
                        '--no-commit-id',
                        '--name-only',
                        '-r',
                        hash,
                    ]);
                    filesChanged = diffOut.trim().split('\n').filter(Boolean);
                }
                catch {
                    // ignore errors on individual commits
                }
                /* v8 ignore start */
                commits.push({
                    hash: hash.slice(0, 8),
                    message,
                    specId: linkedSpecId,
                    author: author ?? 'unknown',
                    date: date ?? new Date().toISOString(),
                    filesChanged,
                });
                /* v8 ignore end */
            }
        }
    }
    catch {
        // No matching commits
    }
    // Detect commits without SPEC reference (orphan commits)
    try {
        const { stdout: allOut } = await git(projectPath, [
            'log',
            '--all',
            '--format=%H|%s|%an|%aI',
            '-50',
        ]);
        if (allOut.trim()) {
            const lines = allOut.trim().split('\n');
            for (const line of lines) {
                const [hash, message, author, date] = line.split('|');
                if (!hash || !message) {
                    continue;
                }
                if (!/SPEC-\d{3}/i.test(message)) {
                    orphanCommits.push({
                        hash: hash.slice(0, 8),
                        message,
                        author: author ?? 'unknown',
                        date: date ?? new Date().toISOString(),
                    });
                }
            }
        }
    }
    catch {
        // ignore
    }
    const result = {
        action: 'link-commits',
        linkedCommits: commits,
        orphanCommits: orphanCommits.slice(0, 10),
        message: `Found ${commits.length} commit(s) linked to ${specId ?? 'specs'}${orphanCommits.length > 0 ? `. ${orphanCommits.length} commit(s) without spec reference.` : ''}`,
    };
    return {
        content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
    };
}
export async function handleStatus(projectId, _specId) {
    const projectPath = await resolveProjectPath(projectId);
    const { stdout: branchOut } = await git(projectPath, ['rev-parse', '--abbrev-ref', 'HEAD']);
    const currentBranch = branchOut.trim();
    const specMatch = /SPEC-\d{3}/.exec(currentBranch);
    const linkedSpec = specMatch ? specMatch[0] : undefined;
    let uncommittedChanges = 0;
    try {
        const { stdout } = await git(projectPath, ['status', '--porcelain']);
        uncommittedChanges = stdout.trim().split('\n').filter(Boolean).length;
    }
    catch {
        // ignore
    }
    const baseBranch = await resolveBaseBranch(projectPath);
    let commitsAhead = 0;
    if (baseBranch && currentBranch !== baseBranch) {
        try {
            const { stdout } = await git(projectPath, ['rev-list', '--count', `${baseBranch}..HEAD`]);
            commitsAhead = parseInt(stdout.trim(), 10) || 0;
        }
        catch {
            // ignore
        }
    }
    const specsCoveredByCommits = [];
    try {
        const { stdout } = await git(projectPath, ['log', '-50', '--format=%s']);
        const messages = stdout.trim().split('\n');
        const seenSpecs = new Set();
        for (const msg of messages) {
            const matches = msg.match(/SPEC-\d{3}/g);
            if (matches) {
                for (const m of matches) {
                    seenSpecs.add(m);
                }
            }
        }
        specsCoveredByCommits.push(...seenSpecs);
    }
    catch {
        // ignore
    }
    const allSpecs = await specStore.listSpecs(projectId);
    const specsInProgress = allSpecs.filter((s) => s.status === 'implementing').map((s) => s.id);
    // Count commits behind develop for each active branch
    const branchesCommitsBehind = {};
    try {
        const { stdout: branchListOut } = await git(projectPath, [
            'branch',
            '--list',
            '--format=%(refname:short)',
        ]);
        const branches = branchListOut.trim().split('\n').filter(Boolean);
        if (baseBranch) {
            for (const b of branches) {
                if (b === baseBranch) {
                    continue;
                }
                try {
                    const { stdout: behindOut } = await git(projectPath, [
                        'rev-list',
                        '--count',
                        `HEAD..${baseBranch}`,
                    ]);
                    branchesCommitsBehind[b] = parseInt(behindOut.trim(), 10) || 0;
                }
                catch {
                    branchesCommitsBehind[b] = 0;
                }
            }
        }
    }
    catch {
        // ignore
    }
    const status = {
        currentBranch,
        linkedSpec,
        uncommittedChanges,
        commitsAhead,
        specsCoveredByCommits,
        specsInProgress,
    };
    const result = {
        action: 'status',
        branchName: currentBranch,
        status,
        message: ti('tools.manage_git.success', { action: 'status' }),
    };
    return {
        content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
    };
}
//# sourceMappingURL=commit-ops.js.map