/**
 * SyncRepoUseCase
 *
 * Stages local changes, commits them, and pushes to the existing GitHub
 * remote. Drives the SmartDeployButton's "Save changes" / "Save & publish"
 * actions for non-technical users — the word "sync" never appears in the
 * UI but is kept in the use-case name as the canonical engineering term.
 *
 * Pre-conditions enforced here so the route layer can stay thin:
 *   1. The Application exists.
 *   2. The Application has a `gitRemoteUrl` (Publish flow has already run).
 *
 * All progress + errors are appended to the operation log under
 * `OperationLogKind.RepoSync` so the OperationLogsDrawer can show the
 * full history including subprocess stderr on failure.
 */
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 { ApplicationNotFoundError } from '../../../domain/errors/application-not-found.error.js';
import { GitRemoteCreationError } from '../../../domain/errors/git-remote-creation.error.js';
import { OperationLogKind } from '../../../domain/generated/output.js';
const DEFAULT_COMMIT_MESSAGE = 'chore(shep): sync local changes';
let SyncRepoUseCase = class SyncRepoUseCase {
    applicationRepo;
    gitRemoteService;
    opLog;
    constructor(applicationRepo, gitRemoteService, opLog) {
        this.applicationRepo = applicationRepo;
        this.gitRemoteService = gitRemoteService;
        this.opLog = opLog;
    }
    async execute(input) {
        const opKind = OperationLogKind.RepoSync;
        const opId = input.applicationId;
        await this.opLog.info(opKind, opId, 'Starting save & backup');
        const app = await this.applicationRepo.findById(input.applicationId);
        if (!app) {
            await this.opLog.error(opKind, opId, `Application not found: ${input.applicationId}`);
            throw new ApplicationNotFoundError(input.applicationId);
        }
        if (!app.gitRemoteUrl) {
            await this.opLog.error(opKind, opId, 'Application has no git remote — Publish to GitHub flow must run first');
            throw new GitRemoteCreationError('No GitHub repository attached to this app yet — set one up first');
        }
        try {
            const trimmedMessage = input.message?.trim();
            const result = await this.gitRemoteService.commitAndPush({
                cwd: app.repositoryPath,
                message: trimmedMessage && trimmedMessage.length > 0 ? trimmedMessage : DEFAULT_COMMIT_MESSAGE,
                onLog: (level, message, detail) => {
                    // Translate the port's string union into an opLog method call.
                    // Fire-and-forget so a logging hiccup never aborts the sync.
                    const persisted = (() => {
                        switch (level) {
                            case 'debug':
                                return this.opLog.debug(opKind, opId, message, detail);
                            case 'warn':
                                return this.opLog.warn(opKind, opId, message, detail);
                            case 'error':
                                return this.opLog.error(opKind, opId, message, detail);
                            case 'info':
                            default:
                                return this.opLog.info(opKind, opId, message, detail);
                        }
                    })();
                    void persisted;
                },
            });
            if (!result.committed && !result.pushed) {
                await this.opLog.info(opKind, opId, 'Already up to date — nothing to save');
            }
            else if (result.committed && result.pushed) {
                await this.opLog.info(opKind, opId, `Saved & backed up successfully (${result.headSha.slice(0, 7)})`);
            }
            else if (result.pushed) {
                await this.opLog.info(opKind, opId, `Pushed pending commits to GitHub (${result.headSha.slice(0, 7)})`);
            }
            return result;
        }
        catch (err) {
            const message = err instanceof Error ? err.message : String(err);
            await this.opLog.error(opKind, opId, `Save & backup failed: ${message}`, err instanceof Error && err.stack ? err.stack : undefined);
            throw err;
        }
    }
};
SyncRepoUseCase = __decorate([
    injectable(),
    __param(0, inject('IApplicationRepository')),
    __param(1, inject('IGitRemoteService')),
    __param(2, inject('IOperationLogService')),
    __metadata("design:paramtypes", [Object, Object, Object])
], SyncRepoUseCase);
export { SyncRepoUseCase };
