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 { injectable, inject } from 'tsyringe';
let DetectDuplicatesUseCase = class DetectDuplicatesUseCase {
    intakeRepo;
    workItemRepo;
    constructor(intakeRepo, workItemRepo) {
        this.intakeRepo = intakeRepo;
        this.workItemRepo = workItemRepo;
    }
    async execute(input) {
        const item = await this.intakeRepo.findById(input.intakeItemId);
        if (!item) {
            return { ok: false, error: `Intake item not found: "${input.intakeItemId}"` };
        }
        const workItems = await this.workItemRepo.listByProject(item.projectId);
        if (workItems.length === 0) {
            return { ok: true, candidates: [] };
        }
        const queryTokens = this.tokenize(`${item.title} ${item.description ?? ''}`);
        const scored = workItems
            .map((wi) => {
            const wiTokens = this.tokenize(`${wi.title} ${wi.description ?? ''}`);
            const score = this.jaccardSimilarity(queryTokens, wiTokens);
            return { workItem: wi, score };
        })
            .filter((c) => c.score > 0)
            .sort((a, b) => b.score - a.score);
        const maxResults = input.limit ?? 5;
        return { ok: true, candidates: scored.slice(0, maxResults) };
    }
    tokenize(text) {
        return new Set(text
            .toLowerCase()
            .replace(/[^a-z0-9\s]/g, '')
            .split(/\s+/)
            .filter((t) => t.length > 2));
    }
    jaccardSimilarity(a, b) {
        if (a.size === 0 || b.size === 0)
            return 0;
        let intersection = 0;
        for (const token of a) {
            if (b.has(token))
                intersection++;
        }
        const union = a.size + b.size - intersection;
        return union === 0 ? 0 : intersection / union;
    }
};
DetectDuplicatesUseCase = __decorate([
    injectable(),
    __param(0, inject('IIntakeItemRepository')),
    __param(1, inject('IWorkItemRepository')),
    __metadata("design:paramtypes", [Object, Object])
], DetectDuplicatesUseCase);
export { DetectDuplicatesUseCase };
