/**
 * GenerateMonthlyRecapUseCase — spec 097, FR-31.
 *
 * For a given UTC `YYYY-MM` bucket, gathers recognition events + the
 * contributors involved and produces a markdown recap artifact. Pure: no
 * publishing, no side-effects. The artifact is the single source of
 * truth that `PublishMonthlyRecapUseCase` fans out across channels.
 */
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 { RecognitionKind, } from '../../../domain/generated/output.js';
const YEAR_MONTH_PATTERN = /^\d{4}-(0[1-9]|1[0-2])$/;
let GenerateMonthlyRecapUseCase = class GenerateMonthlyRecapUseCase {
    contributors;
    events;
    constructor(contributors, events) {
        this.contributors = contributors;
        this.events = events;
    }
    async execute(input) {
        if (!YEAR_MONTH_PATTERN.test(input.yearMonth)) {
            throw new Error(`Invalid yearMonth: "${input.yearMonth}"; expected YYYY-MM.`);
        }
        const events = await this.events.findByMonth(input.yearMonth);
        const contributorIds = new Set(events.map((e) => e.contributorId));
        const contributorList = [];
        for (const id of contributorIds) {
            const contributor = await this.contributors.findById(id);
            if (contributor)
                contributorList.push(contributor);
        }
        const stats = computeStats(events, contributorList);
        const artifact = renderArtifact(input, events, contributorList, stats);
        return { artifact, stats };
    }
};
GenerateMonthlyRecapUseCase = __decorate([
    injectable(),
    __param(0, inject('IContributorRepository')),
    __param(1, inject('IRecognitionEventRepository')),
    __metadata("design:paramtypes", [Object, Object])
], GenerateMonthlyRecapUseCase);
export { GenerateMonthlyRecapUseCase };
function computeStats(events, contributors) {
    const newContributors = events.filter((e) => e.kind === RecognitionKind.FirstPR || e.kind === RecognitionKind.FirstIssue).length;
    const prsRecognized = events.filter((e) => e.kind === RecognitionKind.FirstPR || e.kind === RecognitionKind.NthPR).length;
    const laneCounts = new Map();
    for (const c of contributors) {
        if (!c.lane)
            continue;
        laneCounts.set(c.lane, (laneCounts.get(c.lane) ?? 0) + 1);
    }
    const topLane = pickTop(laneCounts);
    const eventsByContributor = new Map();
    for (const e of events) {
        eventsByContributor.set(e.contributorId, (eventsByContributor.get(e.contributorId) ?? 0) + 1);
    }
    const topContributorId = pickTop(eventsByContributor);
    const topContributorLogin = topContributorId
        ? contributors.find((c) => c.id === topContributorId)?.githubLogin
        : undefined;
    return {
        totalEvents: events.length,
        newContributors,
        prsRecognized,
        topLane,
        topContributorLogin,
    };
}
function pickTop(counts) {
    let bestKey;
    let bestCount = -1;
    for (const [key, count] of counts) {
        if (count > bestCount) {
            bestKey = key;
            bestCount = count;
        }
    }
    return bestKey;
}
function renderArtifact(input, events, contributors, stats) {
    const project = input.projectName ?? 'Shep';
    const title = `${project} — ${input.yearMonth} contributor recap`;
    const lines = [
        `# ${title}`,
        '',
        `_${stats.totalEvents} recognition events · ${stats.newContributors} new contributor(s) · ${stats.prsRecognized} PR(s) recognized_`,
        '',
    ];
    if (stats.topLane) {
        lines.push(`**Most active lane:** \`${stats.topLane}\``);
    }
    if (stats.topContributorLogin) {
        lines.push(`**Top contributor:** @${stats.topContributorLogin}`);
    }
    lines.push('', '## Contributors', '');
    if (contributors.length === 0) {
        lines.push('_No recognized contributors this month._');
    }
    else {
        for (const c of [...contributors].sort((a, b) => a.githubLogin.localeCompare(b.githubLogin))) {
            const lane = c.lane ? ` · \`${c.lane}\`` : '';
            lines.push(`- @${c.githubLogin}${lane}`);
        }
    }
    lines.push('', '## Highlights', '');
    if (events.length === 0) {
        lines.push('_No recognition events this month._');
    }
    else {
        for (const e of [...events].sort((a, b) => Date.parse(a.occurredAt) - Date.parse(b.occurredAt))) {
            lines.push(`- ${describeEvent(e, contributors)}`);
        }
    }
    return {
        recapId: input.yearMonth,
        title,
        body: lines.join('\n'),
        periodStartIso: `${input.yearMonth}-01T00:00:00.000Z`,
    };
}
function describeEvent(event, contributors) {
    const contributor = contributors.find((c) => c.id === event.contributorId);
    const who = contributor ? `@${contributor.githubLogin}` : 'a contributor';
    switch (event.kind) {
        case RecognitionKind.FirstPR:
            return `${who} merged their first PR (#${event.prNumber}).`;
        case RecognitionKind.NthPR:
            return `${who} merged PR #${event.prNumber}.`;
        case RecognitionKind.FirstIssue:
            return `${who} opened their first issue.`;
        case RecognitionKind.MonthlyShoutout:
            return `${who} earned a monthly shoutout.`;
    }
}
