"""
Tests for `NominationIntakeFilter` in scripts/calibrate_helpers.py.

Covers tasks 2.1/2.2 of the calibrate-assessment-inventory change: the
deterministic, no-model filter that runs between haiku nomination and the
strong-model judge (lifecycle-spec.md §8 step 3, calibrate spec's
"Deterministic Nomination Intake Filter" requirement).

sys.path is patched here (no shared conftest), matching the existing
tests/test_calibrate_helpers.py pattern.
"""

from __future__ import annotations

import sys
from pathlib import Path

_SCRIPTS_DIR = Path(__file__).parent.parent / "scripts"
if str(_SCRIPTS_DIR) not in sys.path:
    sys.path.insert(0, str(_SCRIPTS_DIR))

from calibrate_helpers import NominationIntakeFilter  # noqa: E402


def _rejected(glob, lifetime, why="why", consider_instead=None):
    d = {
        "glob": glob,
        "lifetime": lifetime,
        "why": why,
        "rejected_by": "judge",
        "judged_on": "2026-07-15",
    }
    if consider_instead is not None:
        d["consider_instead"] = consider_instead
    return d


def _consult(glob, question="q?"):
    return {
        "glob": glob,
        "question": question,
        "evidence": "e",
        "cluster_key": "k",
        "asked_on": "2026-07-15",
    }


class TestExactRepeatDrop:
    def test_exact_glob_and_lifetime_match_is_dropped_and_logged(self):
        rejected = [_rejected("docs/research/**", "temporary")]
        filt = NominationIntakeFilter(rejected=rejected, consults=[])

        nominations = [{"glob": "docs/research/**", "lifetime": "temporary"}]
        shortlist = ["docs/research/notes.md"]

        result = filt.filter(nominations, shortlist)

        assert result["survivors"] == []
        assert len(result["dropped"]) == 1
        assert result["dropped"][0]["glob"] == "docs/research/**"
        assert result["dropped"][0]["lifetime"] == "temporary"

    def test_same_glob_different_lifetime_is_not_dropped(self):
        rejected = [_rejected("docs/research/**", "temporary")]
        filt = NominationIntakeFilter(rejected=rejected, consults=[])

        nominations = [{"glob": "docs/research/**", "lifetime": "keep"}]
        shortlist = ["docs/research/notes.md"]

        result = filt.filter(nominations, shortlist)

        assert len(result["survivors"]) == 1
        assert result["dropped"] == []


class TestVariantAnnotation:
    def test_variant_survives_annotated_with_related_rejection(self):
        # #52 worked example: docs/research/** -> temporary was rejected;
        # docs/research/drafts/** -> temporary is a narrower variant whose
        # match set intersects the rejected glob's match set on the
        # shortlist -- it survives, annotated with the rejection.
        rejected = [
            _rejected(
                "docs/research/**",
                "temporary",
                why="findings docs other artifacts link to",
                consider_instead="an extract-to-vault rule",
            )
        ]
        filt = NominationIntakeFilter(rejected=rejected, consults=[])

        nominations = [{"glob": "docs/research/drafts/**", "lifetime": "temporary"}]
        shortlist = [
            "docs/research/drafts/outline.md",
            "docs/research/other-notes.md",
        ]

        result = filt.filter(nominations, shortlist)

        assert len(result["survivors"]) == 1
        survivor = result["survivors"][0]
        assert survivor["glob"] == "docs/research/drafts/**"
        assert len(survivor["related_rejections"]) == 1
        related = survivor["related_rejections"][0]
        assert related["glob"] == "docs/research/**"
        assert related["why"] == "findings docs other artifacts link to"
        assert related["consider_instead"] == "an extract-to-vault rule"
        assert result["dropped"] == []

    def test_no_annotation_when_match_sets_do_not_intersect(self):
        rejected = [_rejected("docs/research/**", "temporary")]
        filt = NominationIntakeFilter(rejected=rejected, consults=[])

        nominations = [{"glob": "docs/other-area/**", "lifetime": "temporary"}]
        # shortlist has no path that both globs could match in common
        shortlist = ["docs/research/notes.md", "docs/other-area/thing.md"]

        result = filt.filter(nominations, shortlist)

        assert len(result["survivors"]) == 1
        survivor = result["survivors"][0]
        assert survivor["related_rejections"] == []


class TestOpenConsultsPassThrough:
    def test_open_consults_pass_through_even_with_no_nominations(self):
        consults = [_consult("docs/orchestration-audit/*.md")]
        filt = NominationIntakeFilter(rejected=[], consults=consults)

        result = filt.filter([], [])

        assert result["consults"] == consults
        assert result["survivors"] == []
        assert result["dropped"] == []

    def test_open_consults_pass_through_alongside_survivors(self):
        consults = [_consult("docs/orchestration-audit/*.md")]
        filt = NominationIntakeFilter(rejected=[], consults=consults)

        nominations = [{"glob": "a/*.md", "lifetime": "keep"}]
        result = filt.filter(nominations, ["a/x.md"])

        assert result["consults"] == consults
        assert len(result["survivors"]) == 1
