import { execSync } from 'node:child_process';
import { getLogger } from '../utils/logger.js';
export class GitService {
    db;
    synapseManager;
    logger = getLogger();
    constructor(db, synapseManager) {
        this.db = db;
        this.synapseManager = synapseManager;
    }
    /**
     * Get current git info for context enrichment
     */
    getGitContext(cwd) {
        try {
            const opts = cwd ? { cwd, timeout: 5000 } : { timeout: 5000 };
            const branch = execSync('git rev-parse --abbrev-ref HEAD', { ...opts, encoding: 'utf8' }).trim();
            const diff = execSync('git diff --stat HEAD', { ...opts, encoding: 'utf8' }).trim();
            const lastCommit = execSync('git log -1 --pretty=format:"%H %s"', { ...opts, encoding: 'utf8' }).trim();
            return { branch, diff: diff || null, lastCommit };
        }
        catch {
            return { branch: null, diff: null, lastCommit: null };
        }
    }
    /**
     * Store a git commit and link it to an error
     */
    linkErrorToCommit(errorId, projectId, commitHash, relationship = 'introduced_by') {
        try {
            // Store commit info
            const commitInfo = this.getCommitInfo(commitHash);
            if (commitInfo) {
                this.db.prepare(`
          INSERT OR IGNORE INTO git_commits (project_id, commit_hash, message, author, timestamp, files_changed, insertions, deletions)
          VALUES (?, ?, ?, ?, ?, ?, ?, ?)
        `).run(projectId, commitInfo.hash, commitInfo.message, commitInfo.author, commitInfo.timestamp, commitInfo.filesChanged, commitInfo.insertions, commitInfo.deletions);
            }
            // Link error to commit
            this.db.prepare(`
        INSERT OR IGNORE INTO error_commits (error_id, commit_hash, relationship)
        VALUES (?, ?, ?)
      `).run(errorId, commitHash, relationship);
            this.logger.info(`Linked error #${errorId} to commit ${commitHash.slice(0, 8)} (${relationship})`);
        }
        catch (err) {
            this.logger.warn(`Failed to link error to commit: ${err}`);
        }
    }
    /**
     * Find which commit introduced an error
     */
    findIntroducingCommit(errorId) {
        const rows = this.db.prepare(`
      SELECT ec.commit_hash, ec.relationship, gc.message
      FROM error_commits ec
      LEFT JOIN git_commits gc ON ec.commit_hash = gc.commit_hash
      WHERE ec.error_id = ?
      ORDER BY ec.created_at DESC
    `).all(errorId);
        return rows.map(r => ({
            commitHash: r.commit_hash,
            message: r.message ?? 'unknown',
            relationship: r.relationship,
        }));
    }
    /**
     * Find errors introduced by a specific commit
     */
    findErrorsByCommit(commitHash) {
        const rows = this.db.prepare(`
      SELECT error_id, relationship FROM error_commits WHERE commit_hash = ?
    `).all(commitHash);
        return rows.map(r => ({ errorId: r.error_id, relationship: r.relationship }));
    }
    /**
     * Capture current git diff for error context
     */
    captureDiff(cwd) {
        try {
            const opts = cwd ? { cwd, timeout: 5000, encoding: 'utf8' } : { timeout: 5000, encoding: 'utf8' };
            const diff = execSync('git diff HEAD --no-color', opts).trim();
            // Truncate to avoid huge diffs
            return diff.length > 5000 ? diff.slice(0, 5000) + '\n... (truncated)' : diff || null;
        }
        catch {
            return null;
        }
    }
    getCommitInfo(hash, cwd) {
        try {
            const opts = cwd ? { cwd, timeout: 5000, encoding: 'utf8' } : { timeout: 5000, encoding: 'utf8' };
            const info = execSync(`git log -1 --pretty=format:"%H|||%s|||%an|||%aI" ${hash}`, opts).trim();
            const [commitHash, message, author, timestamp] = info.split('|||');
            const stat = execSync(`git diff --stat ${hash}~1..${hash}`, opts).trim();
            const statMatch = stat.match(/(\d+) files? changed(?:, (\d+) insertions?\(\+\))?(?:, (\d+) deletions?\(-\))?/);
            return {
                hash: commitHash ?? hash,
                message: message ?? '',
                author: author ?? '',
                timestamp: timestamp ?? new Date().toISOString(),
                filesChanged: parseInt(statMatch?.[1] ?? '0', 10),
                insertions: parseInt(statMatch?.[2] ?? '0', 10),
                deletions: parseInt(statMatch?.[3] ?? '0', 10),
            };
        }
        catch {
            return null;
        }
    }
}
//# sourceMappingURL=git.service.js.map