import {
  countRecallTokenOverlap,
  normalizeRecallTokens
} from "./chunk-DT5TVLJE.js";

// src/direct-answer.ts
var FILTER_LABELS = {
  nonActiveStatus: "non-active-status",
  notTrustedZone: "not-trusted-zone",
  ineligibleTaxonomyBucket: "ineligible-taxonomy-bucket",
  belowImportanceFloor: "below-importance-floor",
  entityRefMismatch: "entity-ref-mismatch",
  belowTokenOverlapFloor: "below-token-overlap-floor"
};
function isDirectAnswerEligible(input) {
  const { query, candidates, config, queryEntityRefs } = input;
  if (!config.enabled) {
    return {
      eligible: false,
      reason: "disabled",
      narrative: "direct-answer tier is disabled",
      filteredBy: []
    };
  }
  const queryTokens = new Set(normalizeRecallTokens(query));
  if (queryTokens.size === 0) {
    return {
      eligible: false,
      reason: "empty-query",
      narrative: "query has no searchable tokens after normalization",
      filteredBy: []
    };
  }
  if (candidates.length === 0) {
    return {
      eligible: false,
      reason: "no-candidates",
      narrative: "no candidates supplied",
      filteredBy: []
    };
  }
  const filteredBy = [];
  let working = candidates;
  working = applyFilter(working, filteredBy, FILTER_LABELS.nonActiveStatus, (c) => {
    const status = c.memory.frontmatter.status ?? "active";
    return status === "active";
  });
  working = applyFilter(
    working,
    filteredBy,
    FILTER_LABELS.notTrustedZone,
    (c) => c.trustZone === "trusted"
  );
  working = applyFilter(
    working,
    filteredBy,
    FILTER_LABELS.ineligibleTaxonomyBucket,
    (c) => c.taxonomyBucket !== null && config.eligibleTaxonomyBuckets.includes(c.taxonomyBucket)
  );
  working = applyFilter(working, filteredBy, FILTER_LABELS.belowImportanceFloor, (c) => {
    if (c.memory.frontmatter.verificationState === "user_confirmed") return true;
    return c.importanceScore >= config.importanceFloor;
  });
  if (queryEntityRefs && queryEntityRefs.length > 0) {
    const normRefs = new Set(queryEntityRefs.map((r) => r.toLowerCase()));
    working = applyFilter(working, filteredBy, FILTER_LABELS.entityRefMismatch, (c) => {
      const ref = c.memory.frontmatter.entityRef;
      if (!ref) return true;
      return normRefs.has(ref.toLowerCase());
    });
  }
  if (working.length === 0) {
    return {
      eligible: false,
      reason: "no-eligible-candidates",
      narrative: "no candidates survived eligibility filters",
      filteredBy
    };
  }
  const scored = working.map((candidate) => {
    const searchable = `${candidate.memory.frontmatter.tags?.join(" ") ?? ""} ${candidate.memory.content}`.trim();
    const matches = countRecallTokenOverlap(queryTokens, searchable);
    return { candidate, tokenOverlap: matches / queryTokens.size };
  });
  const overlapSurvivors = scored.filter((s) => s.tokenOverlap >= config.tokenOverlapFloor);
  if (overlapSurvivors.length < scored.length) {
    filteredBy.push(FILTER_LABELS.belowTokenOverlapFloor);
  }
  if (overlapSurvivors.length === 0) {
    return {
      eligible: false,
      reason: "below-token-overlap-floor",
      narrative: `no candidate met token-overlap floor ${config.tokenOverlapFloor}`,
      filteredBy
    };
  }
  overlapSurvivors.sort(compareScored);
  if (overlapSurvivors.length >= 2) {
    const topScore = scoreFor(overlapSurvivors[0]);
    const secondScore = scoreFor(overlapSurvivors[1]);
    if (topScore - secondScore < config.ambiguityMargin) {
      return {
        eligible: false,
        reason: "ambiguous",
        narrative: `top two candidates within ambiguityMargin ${config.ambiguityMargin}`,
        filteredBy
      };
    }
  }
  const winner = overlapSurvivors[0];
  const bucket = winner.candidate.taxonomyBucket ?? "unknown";
  return {
    eligible: true,
    reason: "eligible",
    winner: winner.candidate,
    tokenOverlap: winner.tokenOverlap,
    narrative: `trusted ${bucket}, unambiguous, token-overlap ${winner.tokenOverlap.toFixed(2)}`,
    filteredBy
  };
}
function applyFilter(working, filteredBy, label, keep) {
  const before = working.length;
  const next = working.filter(keep);
  if (next.length < before) filteredBy.push(label);
  return next;
}
function scoreFor(s) {
  return s.candidate.matchScore ?? s.tokenOverlap;
}
function compareScored(a, b) {
  const diff = scoreFor(b) - scoreFor(a);
  if (diff !== 0) return diff;
  return a.candidate.memory.path.localeCompare(b.candidate.memory.path);
}

export {
  FILTER_LABELS,
  isDirectAnswerEligible
};
//# sourceMappingURL=chunk-Y4FHOFJ2.js.map