import type { Logger } from "pino";
import type { RepoConfig, JiraIssue, ScoredRepo } from "@/types/index.js";
import { REPO_SELECTOR } from "@/core/constants.js";
import type { RepoRegistry } from "./registry.js";

export class RepoSelector {
  constructor(
    private readonly registry: RepoRegistry,
    private readonly logger: Logger,
  ) {}

  select(issue: JiraIssue): RepoConfig | null {
    const parentContext = issue.parent
      ? `${issue.parent.summary} ${issue.parent.description ?? ""}`
      : "";
    const ticketText = normalizeText(
      `${issue.summary} ${issue.description ?? ""} ${issue.acceptanceCriteria ?? ""} ${issue.stacktrace ?? ""} ${parentContext}`,
    );
    const ticketWords = new Set(ticketText.split(/\s+/).filter(Boolean));

    const scored: ScoredRepo[] = this.registry.getAll().map((repo) => {
      let score = 0;

      for (const keyword of repo.keywords) {
        const normalizedKeyword = normalizeText(keyword);
        if (!normalizedKeyword) continue;
        if (ticketText.includes(normalizedKeyword) || ticketWords.has(normalizedKeyword)) {
          score += REPO_SELECTOR.KEYWORD_WEIGHT;
        }
      }

      const descriptionWords = normalizeText(repo.description)
        .split(/\s+/)
        .filter((w) => w.length > 2);
      for (const word of descriptionWords) {
        if (ticketWords.has(word)) {
          score += REPO_SELECTOR.DESCRIPTION_WORD_WEIGHT;
        }
      }

      return { repo, score };
    });

    scored.sort((a, b) => b.score - a.score);

    const best = scored[0];
    if (!best || best.score < REPO_SELECTOR.MIN_SCORE_THRESHOLD) {
      this.logger.warn(
        { issueKey: issue.key, scores: scored.map((s) => ({ name: s.repo.name, score: s.score })) },
        "No confident repo match for ticket",
      );
      return null;
    }

    this.logger.info(
      {
        issueKey: issue.key,
        selectedRepo: best.repo.name,
        score: best.score,
        allScores: scored.map((s) => ({ name: s.repo.name, score: s.score })),
      },
      "repo_selected",
    );

    return best.repo;
  }
}

function normalizeText(text: string): string {
  return text
    .toLowerCase()
    .replace(/[^a-z0-9\s]/g, " ")
    .replace(/\s+/g, " ")
    .trim();
}
