/**
 * SQLite RecognitionEvent Repository (spec 097, FR-22 / NFR-11).
 *
 * Backed by the `recognition_events` table (migration 102). The `insert`
 * method uses `INSERT … ON CONFLICT DO NOTHING` so that duplicate webhook
 * deliveries cannot double-award the same contributor for the same PR.
 *
 * The `inserted` flag returned by the upsert reflects whether a row was
 * actually written (true) or skipped because the UNIQUE constraint fired
 * (false). Callers use this flag to short-circuit downstream side-effects
 * like `IAllContributorsWriter.appendContributor`.
 */
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 { toDatabase, fromDatabase, } from '../persistence/sqlite/mappers/recognition-event.mapper.js';
/**
 * Returns the [start, endExclusive) UTC ms boundaries of the given
 * 'YYYY-MM' bucket. Throws if the input is not a valid year-month string.
 */
function monthBoundsUtc(yearMonth) {
    const match = /^(\d{4})-(\d{2})$/.exec(yearMonth);
    if (!match) {
        throw new Error(`Invalid yearMonth bucket: '${yearMonth}'. Expected 'YYYY-MM'.`);
    }
    const year = Number(match[1]);
    const month = Number(match[2]) - 1;
    const start = Date.UTC(year, month, 1);
    const endExclusive = Date.UTC(year, month + 1, 1);
    return { start, endExclusive };
}
let SQLiteRecognitionEventRepository = class SQLiteRecognitionEventRepository {
    db;
    constructor(db) {
        this.db = db;
    }
    async insert(event) {
        const row = toDatabase(event);
        const result = this.db
            .prepare(`INSERT INTO recognition_events
           (id, contributor_id, kind, occurred_at, pr_number, month_recap_id,
            created_at, updated_at)
         VALUES (@id, @contributor_id, @kind, @occurred_at, @pr_number, @month_recap_id,
                 @created_at, @updated_at)
         ON CONFLICT(contributor_id, kind, pr_number) DO NOTHING`)
            .run(row);
        return { inserted: result.changes > 0 };
    }
    async findByContributorId(contributorId) {
        const rows = this.db
            .prepare(`SELECT * FROM recognition_events
           WHERE contributor_id = ?
           ORDER BY occurred_at DESC`)
            .all(contributorId);
        return rows.map(fromDatabase);
    }
    async findByMonth(yearMonth) {
        const { start, endExclusive } = monthBoundsUtc(yearMonth);
        const rows = this.db
            .prepare(`SELECT * FROM recognition_events
           WHERE occurred_at >= ? AND occurred_at < ?
           ORDER BY occurred_at ASC`)
            .all(start, endExclusive);
        return rows.map(fromDatabase);
    }
};
SQLiteRecognitionEventRepository = __decorate([
    injectable(),
    __param(0, inject('Database')),
    __metadata("design:paramtypes", [Object])
], SQLiteRecognitionEventRepository);
export { SQLiteRecognitionEventRepository };
