/**
 * GitCommitService
 *
 * Infrastructure adapter for IGitCommitService. Uses the injected
 * ExecFunction to run `git` commands — same strategy as GitRemoteService
 * and WorktreeService so the service can be unit tested against a
 * stubbed executor without spawning real processes.
 */
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
    return function (target, key) { decorator(target, key, paramIndex); }
};
import { inject, injectable } from 'tsyringe';
import { GitCommitError, GitPushError, } from '../../../application/ports/output/services/git-commit.service.interface.js';
let GitCommitService = class GitCommitService {
    execFile;
    constructor(execFile) {
        this.execFile = execFile;
    }
    async commitChanges(input) {
        const { cwd, message } = input;
        return this.stageAndCommit(cwd, message);
    }
    async commitAndPush(input) {
        const { cwd, message } = input;
        const commitResult = await this.stageAndCommit(cwd, message);
        // Even if nothing was committed right now, there may be earlier
        // local commits ahead of origin — try to push either way.
        if (!(await this.hasOriginRemote(cwd))) {
            throw new GitPushError('No "origin" remote configured for this repository.');
        }
        try {
            await this.execFile('git', ['push', 'origin', 'HEAD'], { cwd });
        }
        catch (err) {
            const messageText = err instanceof Error ? err.message : String(err);
            throw new GitPushError(`git push failed: ${messageText}`);
        }
        return { committed: commitResult.committed, pushed: true };
    }
    async stageAndCommit(cwd, message) {
        try {
            await this.execFile('git', ['add', '-A'], { cwd });
        }
        catch (err) {
            const messageText = err instanceof Error ? err.message : String(err);
            throw new GitCommitError(`git add failed: ${messageText}`);
        }
        // If the working tree is clean, skip the commit entirely.
        const hasStaged = await this.hasStagedChanges(cwd);
        if (!hasStaged) {
            return { committed: false };
        }
        try {
            await this.execFile('git', ['commit', '-m', message], { cwd });
        }
        catch (err) {
            const messageText = err instanceof Error ? err.message : String(err);
            throw new GitCommitError(`git commit failed: ${messageText}`);
        }
        return { committed: true };
    }
    async hasStagedChanges(cwd) {
        try {
            // `git diff --cached --quiet` exits 0 when there are NO staged
            // changes and exits 1 when there are. Use the `--name-only` flag
            // output length instead for cross-platform portability with our
            // ExecFunction signature (which throws on non-zero exit).
            const { stdout } = await this.execFile('git', ['diff', '--cached', '--name-only'], { cwd });
            return stdout.trim().length > 0;
        }
        catch {
            return false;
        }
    }
    async hasOriginRemote(cwd) {
        try {
            const { stdout } = await this.execFile('git', ['remote', 'get-url', 'origin'], { cwd });
            return stdout.trim().length > 0;
        }
        catch {
            return false;
        }
    }
};
GitCommitService = __decorate([
    injectable(),
    __param(0, inject('ExecFunction')),
    __metadata("design:paramtypes", [Function])
], GitCommitService);
export { GitCommitService };
