import { execFileSync, spawnSync } from 'node:child_process';
import { rmSync, existsSync, unlinkSync } from 'node:fs';
import { join } from 'node:path';
import { cleanupOrphanedClone } from '../../../infra/task/index.js';
import { encodeWorktreePath } from '../../../infra/config/project/sessionStore.js';
import { info, success, error as logError, warn } from '../../../shared/ui/index.js';
import { createLogger, getErrorMessage } from '../../../shared/utils/index.js';
import { ensureRootBranchReady, resolveTargetBranch, resolveTargetWorktreePath, } from './taskActionTarget.js';
const log = createLogger('list-tasks');
function getGitCommandErrorDetail(err) {
    if (typeof err === 'object' && err !== null && 'stderr' in err) {
        const stderr = err.stderr;
        if (typeof stderr === 'string' && stderr.trim()) {
            return stderr.trim();
        }
        if (Buffer.isBuffer(stderr)) {
            const text = stderr.toString('utf-8').trim();
            if (text) {
                return text;
            }
        }
    }
    return getErrorMessage(err);
}
export function isBranchMerged(projectDir, branch) {
    const result = spawnSync('git', ['merge-base', '--is-ancestor', branch, 'HEAD'], {
        cwd: projectDir,
        encoding: 'utf-8',
        stdio: 'pipe',
    });
    if (result.error) {
        log.error('Failed to check if branch is merged', {
            branch,
            error: getErrorMessage(result.error),
        });
        return false;
    }
    return result.status === 0;
}
export function tryMergeBranch(projectDir, target) {
    if (!ensureRootBranchReady(projectDir, target, 'try merge')) {
        return false;
    }
    const branch = resolveTargetBranch(target);
    try {
        execFileSync('git', ['merge', '--squash', branch], {
            cwd: projectDir,
            encoding: 'utf-8',
            stdio: 'pipe',
        });
        success(`Squash-merged ${branch} (changes staged, not committed)`);
        info('Run `git status` to see staged changes, `git commit` to finalize, or `git reset` to undo.');
        log.info('Try-merge (squash) completed', { branch });
        return true;
    }
    catch (err) {
        const msg = getGitCommandErrorDetail(err);
        logError(`Squash merge failed: ${msg}`);
        logError('You may need to resolve conflicts manually.');
        log.error('Try-merge (squash) failed', { branch, error: msg });
        return false;
    }
}
export function mergeBranch(projectDir, target) {
    if (!ensureRootBranchReady(projectDir, target, 'merge')) {
        return false;
    }
    const branch = resolveTargetBranch(target);
    const alreadyMerged = isBranchMerged(projectDir, branch);
    try {
        if (alreadyMerged) {
            info(`${branch} is already merged, skipping merge.`);
            log.info('Branch already merged, cleanup only', { branch });
        }
        else {
            execFileSync('git', ['merge', '--no-edit', branch], {
                cwd: projectDir,
                encoding: 'utf-8',
                stdio: 'pipe',
                env: {
                    ...process.env,
                    GIT_MERGE_AUTOEDIT: 'no',
                },
            });
        }
        try {
            execFileSync('git', ['branch', '-d', branch], {
                cwd: projectDir,
                encoding: 'utf-8',
                stdio: 'pipe',
            });
        }
        catch (err) {
            warn(`Could not delete branch ${branch}. You may delete it manually.`);
            log.error('Failed to delete merged branch', {
                branch,
                error: getErrorMessage(err),
            });
        }
        cleanupOrphanedClone(projectDir, branch);
        success(`Merged & cleaned up ${branch}`);
        log.info('Branch merged & cleaned up', { branch, alreadyMerged });
        return true;
    }
    catch (err) {
        const msg = getGitCommandErrorDetail(err);
        logError(`Merge failed: ${msg}`);
        logError('You may need to resolve conflicts manually.');
        log.error('Merge & cleanup failed', { branch, error: msg });
        return false;
    }
}
export function deleteBranch(projectDir, target) {
    const branch = resolveTargetBranch(target);
    const worktreePath = resolveTargetWorktreePath(target);
    try {
        if (worktreePath) {
            if (existsSync(worktreePath)) {
                rmSync(worktreePath, { recursive: true, force: true, maxRetries: 3, retryDelay: 200 });
                log.info('Removed worktree directory', { worktreePath });
            }
            const encodedPath = encodeWorktreePath(worktreePath);
            const sessionFile = join(projectDir, '.takt', 'worktree-sessions', `${encodedPath}.json`);
            if (existsSync(sessionFile)) {
                unlinkSync(sessionFile);
                log.info('Removed worktree-session file', { sessionFile });
            }
            success(`Deleted worktree ${branch}`);
            log.info('Worktree branch deleted', { branch, worktreePath });
            return true;
        }
        execFileSync('git', ['branch', '-D', branch], {
            cwd: projectDir,
            encoding: 'utf-8',
            stdio: 'pipe',
        });
        cleanupOrphanedClone(projectDir, branch);
        success(`Deleted ${branch}`);
        log.info('Branch deleted', { branch });
        return true;
    }
    catch (err) {
        const msg = getErrorMessage(err);
        logError(`Delete failed: ${msg}`);
        log.error('Delete failed', { branch, error: msg });
        return false;
    }
}
//# sourceMappingURL=taskBranchLifecycleActions.js.map