"""Tests for DUO matcher."""

from __future__ import annotations

from ai4gh.specs.duo.matcher import DUOMatcher
from ai4gh.specs.duo.models import (
    DataUseCondition,
    DUOModifier,
    ResearchPurpose,
)


class TestDUOMatcher:
    def setup_method(self) -> None:
        self.matcher = DUOMatcher()

    def test_no_conditions(self) -> None:
        purpose = ResearchPurpose(codes=["DUO:0000042"])
        result = self.matcher.check_compatibility([], purpose)
        assert result.compatible is True
        assert "No data use conditions" in result.reason

    def test_permissive_no_restriction(self) -> None:
        conditions = [DataUseCondition(code=DUOModifier.NO_RESTRICTION.value)]
        purpose = ResearchPurpose(codes=["DUO:0000042"])
        result = self.matcher.check_compatibility(conditions, purpose)
        assert result.compatible is True

    def test_permissive_general_research(self) -> None:
        conditions = [DataUseCondition(code=DUOModifier.GENERAL_RESEARCH_USE.value)]
        purpose = ResearchPurpose(codes=["DUO:0000042"])
        result = self.matcher.check_compatibility(conditions, purpose)
        assert result.compatible is True

    def test_disease_specific_match(self) -> None:
        conditions = [
            DataUseCondition(
                code=DUOModifier.DISEASE_SPECIFIC.value,
                disease_id="MONDO:0005015",
            )
        ]
        purpose = ResearchPurpose(
            codes=["DUO:0000007"],
            disease_id="MONDO:0005015",
        )
        result = self.matcher.check_compatibility(conditions, purpose)
        assert result.compatible is True

    def test_disease_specific_mismatch(self) -> None:
        conditions = [
            DataUseCondition(
                code=DUOModifier.DISEASE_SPECIFIC.value,
                disease_id="MONDO:0005015",
            )
        ]
        purpose = ResearchPurpose(
            codes=["DUO:0000007"],
            disease_id="MONDO:0009999",
        )
        result = self.matcher.check_compatibility(conditions, purpose)
        assert result.compatible is False
        assert len(result.blocking_conditions) == 1

    def test_not_for_profit_academic(self) -> None:
        conditions = [DataUseCondition(code=DUOModifier.NOT_FOR_PROFIT.value)]
        purpose = ResearchPurpose(codes=["DUO:0000042"], is_for_profit=False)
        result = self.matcher.check_compatibility(conditions, purpose)
        assert result.compatible is True

    def test_not_for_profit_commercial(self) -> None:
        conditions = [DataUseCondition(code=DUOModifier.NOT_FOR_PROFIT.value)]
        purpose = ResearchPurpose(codes=["DUO:0000042"], is_for_profit=True)
        result = self.matcher.check_compatibility(conditions, purpose)
        assert result.compatible is False

    def test_non_commercial_commercial(self) -> None:
        conditions = [DataUseCondition(code=DUOModifier.NON_COMMERCIAL.value)]
        purpose = ResearchPurpose(codes=["DUO:0000042"], is_for_profit=True)
        result = self.matcher.check_compatibility(conditions, purpose)
        assert result.compatible is False

    def test_institution_specific_match(self) -> None:
        conditions = [
            DataUseCondition(
                code=DUOModifier.INSTITUTION_SPECIFIC.value,
                institution="MIT",
            )
        ]
        purpose = ResearchPurpose(codes=["DUO:0000042"], institution="MIT")
        result = self.matcher.check_compatibility(conditions, purpose)
        assert result.compatible is True

    def test_institution_specific_mismatch(self) -> None:
        conditions = [
            DataUseCondition(
                code=DUOModifier.INSTITUTION_SPECIFIC.value,
                institution="MIT",
            )
        ]
        purpose = ResearchPurpose(codes=["DUO:0000042"], institution="Stanford")
        result = self.matcher.check_compatibility(conditions, purpose)
        assert result.compatible is False

    def test_project_specific_match(self) -> None:
        conditions = [
            DataUseCondition(
                code=DUOModifier.PROJECT_SPECIFIC.value,
                project="GENOMICS-2024",
            )
        ]
        purpose = ResearchPurpose(codes=["DUO:0000042"], project="GENOMICS-2024")
        result = self.matcher.check_compatibility(conditions, purpose)
        assert result.compatible is True

    def test_project_specific_mismatch(self) -> None:
        conditions = [
            DataUseCondition(
                code=DUOModifier.PROJECT_SPECIFIC.value,
                project="GENOMICS-2024",
            )
        ]
        purpose = ResearchPurpose(codes=["DUO:0000042"], project="OTHER-PROJECT")
        result = self.matcher.check_compatibility(conditions, purpose)
        assert result.compatible is False

    def test_multiple_conditions_all_pass(self) -> None:
        conditions = [
            DataUseCondition(code=DUOModifier.GENERAL_RESEARCH_USE.value),
            DataUseCondition(code=DUOModifier.NOT_FOR_PROFIT.value),
        ]
        purpose = ResearchPurpose(codes=["DUO:0000042"], is_for_profit=False)
        result = self.matcher.check_compatibility(conditions, purpose)
        assert result.compatible is True
        assert len(result.matched_conditions) == 2

    def test_multiple_conditions_one_blocks(self) -> None:
        conditions = [
            DataUseCondition(code=DUOModifier.GENERAL_RESEARCH_USE.value),
            DataUseCondition(code=DUOModifier.NOT_FOR_PROFIT.value),
        ]
        purpose = ResearchPurpose(codes=["DUO:0000042"], is_for_profit=True)
        result = self.matcher.check_compatibility(conditions, purpose)
        assert result.compatible is False
        assert len(result.blocking_conditions) == 1
        assert len(result.matched_conditions) == 1

    def test_unknown_condition_passes(self) -> None:
        conditions = [DataUseCondition(code="DUO:9999999")]
        purpose = ResearchPurpose(codes=["DUO:0000042"])
        result = self.matcher.check_compatibility(conditions, purpose)
        assert result.compatible is True
