/**
 * GroomIssueUseCase — spec 097, FR-25.
 *
 * Composes `ClassifyIntoLaneUseCase` and `ProposeAcceptanceCriteriaUseCase`
 * over a fetched issue to produce a structured grooming recommendation:
 *
 *   { lane, difficulty, acceptanceCriteria, suggestedLabels[], welcomeComment }
 *
 * Pure: NO side-effects. Callers (CLI commands, GitHub Actions handlers,
 * web routes) decide whether to apply the result via `IGitHubIssueWriter`,
 * gated through `IContributorActionGate` (NFR-5).
 */
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 { ContributionDifficulty } from '../../../domain/generated/output.js';
import { ClassifyIntoLaneUseCase } from './classify-into-lane.use-case.js';
import { ProposeAcceptanceCriteriaUseCase } from './propose-acceptance-criteria.use-case.js';
const DIFFICULTY_LABEL_HINTS = [
    ['good-first-issue', ContributionDifficulty.GoodFirst],
    ['good first issue', ContributionDifficulty.GoodFirst],
    ['easy', ContributionDifficulty.Easy],
    ['medium', ContributionDifficulty.Medium],
    ['hard', ContributionDifficulty.Hard],
];
let GroomIssueUseCase = class GroomIssueUseCase {
    fetcher;
    classifyIntoLane;
    proposeCriteria;
    constructor(fetcher, classifyIntoLane, proposeCriteria) {
        this.fetcher = fetcher;
        this.classifyIntoLane = classifyIntoLane;
        this.proposeCriteria = proposeCriteria;
    }
    async execute(input) {
        const issue = await this.fetcher.fetchGitHubIssue(input.ref);
        const existingLabels = issue.labels.map((l) => l.toLowerCase());
        const lane = await this.classifyIntoLane.execute({
            title: issue.title,
            body: issue.description,
            existingLabels,
        });
        const criteria = await this.proposeCriteria.execute({
            title: issue.title,
            body: issue.description,
        });
        const difficulty = inferDifficulty(existingLabels, issue.description);
        const suggestedLabels = mergeSuggestedLabels(existingLabels, lane.lane, difficulty);
        const welcomeComment = difficulty === ContributionDifficulty.GoodFirst ? renderWelcomeComment(lane.lane) : undefined;
        return {
            lane: lane.lane,
            difficulty,
            acceptanceCriteria: criteria.markdown,
            suggestedLabels,
            welcomeComment,
        };
    }
};
GroomIssueUseCase = __decorate([
    injectable(),
    __param(0, inject('IExternalIssueFetcher')),
    __param(1, inject(ClassifyIntoLaneUseCase)),
    __param(2, inject(ProposeAcceptanceCriteriaUseCase)),
    __metadata("design:paramtypes", [Object, ClassifyIntoLaneUseCase,
        ProposeAcceptanceCriteriaUseCase])
], GroomIssueUseCase);
export { GroomIssueUseCase };
function inferDifficulty(existingLabels, body) {
    for (const [hint, difficulty] of DIFFICULTY_LABEL_HINTS) {
        if (existingLabels.includes(hint))
            return difficulty;
    }
    const codeBlockCount = (body.match(/```/g) ?? []).length / 2;
    const fileMentions = (body.match(/`[^`]+\.(ts|tsx|md|yml|yaml|json)`/g) ?? []).length;
    if (codeBlockCount === 0 && fileMentions <= 1 && body.length < 600) {
        return ContributionDifficulty.Easy;
    }
    if (fileMentions >= 3 || body.length > 2000)
        return ContributionDifficulty.Hard;
    return ContributionDifficulty.Medium;
}
function mergeSuggestedLabels(existing, lane, difficulty) {
    const merged = new Set(existing);
    merged.add(`lane:${lane}`);
    merged.add(`difficulty:${difficulty}`);
    return [...merged];
}
function renderWelcomeComment(lane) {
    return [
        `Hey there 👋 — this is a good first issue in the **${lane}** lane.`,
        '',
        'A few quick links to get you started:',
        '- `CONTRIBUTING.md` covers the 30-second setup.',
        '- `shep doctor` validates your local environment.',
        '- Drop a comment here and a maintainer will assign it to you.',
    ].join('\n');
}
