/**
 * GitHub Issue Fetcher Service
 *
 * Adapter implementing `IExternalIssueFetcher` against the `gh` CLI.
 * GitHub-specific methods shell out to `gh`; `fetchJiraTicket` is not
 * supported by this adapter and throws `IssueServiceUnavailableError`.
 *
 * Supports owner/repo#number and #number (current repo) formats.
 */
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 { IssueNotFoundError, IssueServiceUnavailableError, } from '../../../application/ports/output/services/external-issue-fetcher.interface.js';
const GH_TIMEOUT_MS = 30_000;
let GitHubIssueFetcher = class GitHubIssueFetcher {
    execFile;
    constructor(execFile) {
        this.execFile = execFile;
    }
    async fetchGitHubIssue(ref) {
        const { issueNumber, repo } = this.parseRef(ref);
        const args = ['issue', 'view', issueNumber];
        if (repo) {
            args.push('--repo', repo);
        }
        args.push('--json', 'title,body,labels,url');
        try {
            const { stdout } = await this.execFile('gh', args, { timeout: GH_TIMEOUT_MS });
            const data = JSON.parse(stdout);
            return {
                title: data.title,
                description: data.body ?? '',
                labels: data.labels.map((l) => l.name),
                url: data.url,
                source: 'github',
            };
        }
        catch (err) {
            throw this.translateError(err, `GitHub issue ${ref}`);
        }
    }
    async fetchJiraTicket(_key) {
        throw new IssueServiceUnavailableError('Jira fetching is not configured for this Shep instance. Configure a Jira adapter to enable it.');
    }
    async getMergedPrCount(owner, repo, login) {
        const args = [
            'pr',
            'list',
            '--repo',
            `${owner}/${repo}`,
            '--state',
            'merged',
            '--author',
            login,
            '--limit',
            '1000',
            '--json',
            'number',
        ];
        try {
            const { stdout } = await this.execFile('gh', args, { timeout: GH_TIMEOUT_MS });
            const items = JSON.parse(stdout || '[]');
            return items.length;
        }
        catch (err) {
            throw this.translateError(err, `merged PR count for ${login} in ${owner}/${repo}`);
        }
    }
    async listIssuesByLabel(owner, repo, label) {
        return this.listIssuesByLabels(owner, repo, [label]);
    }
    async listIssuesByLabels(owner, repo, labels) {
        if (labels.length === 0)
            return [];
        const args = [
            'issue',
            'list',
            '--repo',
            `${owner}/${repo}`,
            '--state',
            'open',
            '--label',
            labels.join(','),
            '--limit',
            '200',
            '--json',
            'number,title,labels,updatedAt,url',
        ];
        try {
            const { stdout } = await this.execFile('gh', args, { timeout: GH_TIMEOUT_MS });
            const items = JSON.parse(stdout || '[]');
            return items.map((i) => ({
                owner,
                repo,
                issueNumber: i.number,
                title: i.title,
                labels: i.labels.map((l) => l.name),
                lastActivityAt: i.updatedAt,
                url: i.url,
            }));
        }
        catch (err) {
            throw this.translateError(err, `issues with labels [${labels.join(',')}] in ${owner}/${repo}`);
        }
    }
    parseRef(ref) {
        const fullMatch = ref.match(/^([^#]+)#(\d+)$/);
        if (fullMatch) {
            return { issueNumber: fullMatch[2], repo: fullMatch[1] };
        }
        const hashMatch = ref.match(/^#(\d+)$/);
        if (hashMatch) {
            return { issueNumber: hashMatch[1] };
        }
        if (/^\d+$/.test(ref)) {
            return { issueNumber: ref };
        }
        throw new IssueNotFoundError(`Invalid GitHub issue reference: ${ref}`);
    }
    translateError(err, context) {
        const error = err instanceof Error ? err : new Error(String(err));
        if (error.code === 'ENOENT') {
            return new IssueServiceUnavailableError('GitHub CLI (gh) is not installed. Install it from https://cli.github.com/');
        }
        if (error.message.includes('Could not resolve')) {
            return new IssueNotFoundError(`${context} not found`);
        }
        return new IssueNotFoundError(`Failed to fetch ${context}: ${error.message}`);
    }
};
GitHubIssueFetcher = __decorate([
    injectable(),
    __param(0, inject('ExecFunction')),
    __metadata("design:paramtypes", [Function])
], GitHubIssueFetcher);
export { GitHubIssueFetcher };
