/**
 * GitLab Merge Request utilities
 *
 * Creates and manages MRs via `glab` CLI.
 */
import { execFileSync } from 'node:child_process';
import { createLogger, getErrorMessage } from '../../shared/utils/index.js';
import { isTaktManagedPrBody } from '../git/format.js';
import { checkGlabCli, fetchAllPages, parseJson, ITEMS_PER_PAGE } from './utils.js';
const log = createLogger('gitlab-mr');
/**
 * Find an open MR for the given branch.
 * Returns undefined if no MR exists.
 */
export function findExistingMr(branch, cwd) {
    const glabStatus = checkGlabCli(cwd);
    if (!glabStatus.available)
        return undefined;
    try {
        const output = execFileSync('glab', ['mr', 'list', '--source-branch', branch, '--state', 'opened', '--output', 'json'], { cwd, encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] });
        const mrs = parseJson(output, 'mr list');
        const first = mrs[0];
        if (!first)
            return undefined;
        return { number: first.iid, url: first.web_url };
    }
    catch (e) {
        log.debug('glab mr list failed, treating as no MR', { error: getErrorMessage(e) });
        return undefined;
    }
}
export function listOpenMrs(cwd) {
    const mrs = fetchAllPages('projects/:id/merge_requests?state=opened', ITEMS_PER_PAGE, 'open merge request list', cwd);
    return mrs.map((mr) => ({
        number: mr.iid,
        author: mr.author.username,
        base_branch: mr.target_branch,
        head_branch: mr.source_branch,
        managed_by_takt: isTaktManagedPrBody(mr.description),
        labels: mr.labels,
        same_repository: mr.source_project_id === mr.target_project_id,
        draft: mr.draft,
        updated_at: mr.updated_at,
    }));
}
/**
 * Create a GitLab Merge Request via `glab mr create`.
 */
export function createMergeRequest(options, cwd) {
    if (options.repo) {
        throw new Error('--repo is not supported with GitLab provider. Use cwd context instead.');
    }
    const glabStatus = checkGlabCli(cwd);
    if (!glabStatus.available) {
        return { success: false, error: glabStatus.error };
    }
    const args = [
        'mr', 'create',
        '--title', options.title,
        '--description', options.body,
        '--source-branch', options.branch,
    ];
    if (options.base) {
        args.push('--target-branch', options.base);
    }
    if (options.draft) {
        args.push('--draft');
    }
    for (const label of options.labels ?? []) {
        args.push('--label', label);
    }
    log.info('Creating MR', { branch: options.branch, title: options.title, draft: options.draft });
    try {
        const output = execFileSync('glab', args, {
            cwd,
            encoding: 'utf-8',
            stdio: ['pipe', 'pipe', 'pipe'],
        });
        const url = output.trim();
        log.info('MR created', { url });
        return { success: true, url };
    }
    catch (err) {
        const errorMessage = getErrorMessage(err);
        log.error('MR creation failed', { error: errorMessage });
        return { success: false, error: errorMessage };
    }
}
/**
 * Add a comment (note) to a GitLab Merge Request.
 */
export function commentOnMr(mrNumber, body, cwd) {
    const glabStatus = checkGlabCli(cwd);
    if (!glabStatus.available) {
        return { success: false, error: glabStatus.error };
    }
    try {
        execFileSync('glab', ['mr', 'note', String(mrNumber), '--message', body], {
            cwd,
            encoding: 'utf-8',
            stdio: ['pipe', 'pipe', 'pipe'],
        });
        return { success: true };
    }
    catch (err) {
        const errorMessage = getErrorMessage(err);
        log.error('MR comment failed', { error: errorMessage });
        return { success: false, error: errorMessage };
    }
}
/**
 * Fetch MR review comments and metadata.
 * Uses `glab mr view` for metadata and `glab api` (paginated) for diffs, notes, and discussions.
 *
 * Throws on failure (MR not found, network error, etc.).
 */
export function fetchMrReviewComments(mrNumber, cwd) {
    log.debug('Fetching MR review comments', { mrNumber });
    const rawMr = execFileSync('glab', ['mr', 'view', String(mrNumber), '--output', 'json'], { cwd, encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] });
    const mrData = parseJson(rawMr, `mr view #${mrNumber}`);
    const diffs = fetchAllPages(`projects/:id/merge_requests/${mrNumber}/diffs`, ITEMS_PER_PAGE, `mr #${mrNumber} diffs`, cwd);
    const files = diffs.map(d => d.new_path);
    const allNotes = fetchAllPages(`projects/:id/merge_requests/${mrNumber}/notes`, ITEMS_PER_PAGE, `mr #${mrNumber} notes`, cwd);
    const comments = [];
    for (const note of allNotes) {
        if (!note.system && !note.position) {
            comments.push({ author: note.author.username, body: note.body });
        }
    }
    const allDiscussions = fetchAllPages(`projects/:id/merge_requests/${mrNumber}/discussions`, ITEMS_PER_PAGE, `mr #${mrNumber} discussions`, cwd);
    const reviews = [];
    for (const discussion of allDiscussions) {
        for (const note of discussion.notes) {
            if (note.position) {
                reviews.push({
                    author: note.author.username,
                    body: note.body,
                    path: note.position.new_path,
                    line: note.position.new_line,
                });
            }
        }
    }
    return {
        number: mrData.iid,
        title: mrData.title,
        body: mrData.description ?? '',
        url: mrData.web_url,
        headRefName: mrData.source_branch,
        baseRefName: mrData.target_branch,
        comments,
        reviews,
        files,
    };
}
export function mergeMr(mrNumber, cwd) {
    const glabStatus = checkGlabCli(cwd);
    if (!glabStatus.available) {
        return { success: false, error: glabStatus.error };
    }
    try {
        execFileSync('glab', ['mr', 'merge', String(mrNumber), '--remove-source-branch', '--yes'], {
            cwd,
            encoding: 'utf-8',
            stdio: ['pipe', 'pipe', 'pipe'],
        });
        return { success: true };
    }
    catch (err) {
        const errorMessage = getErrorMessage(err);
        log.error('MR merge failed', { error: errorMessage });
        return { success: false, error: errorMessage };
    }
}
export function closeMr(mrNumber, cwd) {
    const glabStatus = checkGlabCli(cwd);
    if (!glabStatus.available) {
        return { success: false, error: glabStatus.error };
    }
    try {
        execFileSync('glab', ['mr', 'close', String(mrNumber)], {
            cwd,
            encoding: 'utf-8',
            stdio: ['pipe', 'pipe', 'pipe'],
        });
        return { success: true };
    }
    catch (err) {
        const errorMessage = getErrorMessage(err);
        log.error('MR close failed', { error: errorMessage });
        return { success: false, error: errorMessage };
    }
}
//# sourceMappingURL=pr.js.map