"""DUO compatibility matching engine.

Evaluates whether a researcher's declared purpose is compatible
with the data use conditions applied to a dataset.
"""

from __future__ import annotations

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


class DUOMatcher:
    """Evaluates DUO compatibility between conditions and purposes."""

    # Conditions that always block if present and unmet
    BLOCKING_CONDITIONS = {
        DUOModifier.NOT_FOR_PROFIT.value,
        DUOModifier.NON_COMMERCIAL.value,
        DUOModifier.ETHICS_APPROVAL_REQUIRED.value,
        DUOModifier.INSTITUTION_SPECIFIC.value,
        DUOModifier.PROJECT_SPECIFIC.value,
    }

    # Permissive conditions that broadly allow use
    PERMISSIVE_CONDITIONS = {
        DUOModifier.NO_RESTRICTION.value,
        DUOModifier.GENERAL_RESEARCH_USE.value,
    }

    def check_compatibility(
        self,
        conditions: list[DataUseCondition],
        purpose: ResearchPurpose,
    ) -> CompatibilityResult:
        """Check if a research purpose is compatible with data use conditions.

        Args:
            conditions: Data use conditions on the dataset.
            purpose: The researcher's declared purpose.

        Returns:
            Compatibility result with details.
        """
        if not conditions:
            return CompatibilityResult(
                compatible=True,
                reason="No data use conditions specified",
            )

        blocking: list[DataUseCondition] = []
        matched: list[DataUseCondition] = []

        for condition in conditions:
            if condition.code in self.PERMISSIVE_CONDITIONS:
                matched.append(condition)
                continue

            if condition.code == DUOModifier.DISEASE_SPECIFIC.value:
                if condition.disease_id and purpose.disease_id != condition.disease_id:
                    blocking.append(condition)
                else:
                    matched.append(condition)
                continue

            if condition.code in {
                DUOModifier.NOT_FOR_PROFIT.value,
                DUOModifier.NON_COMMERCIAL.value,
            }:
                if purpose.is_for_profit:
                    blocking.append(condition)
                else:
                    matched.append(condition)
                continue

            if condition.code == DUOModifier.INSTITUTION_SPECIFIC.value:
                if condition.institution and purpose.institution != condition.institution:
                    blocking.append(condition)
                else:
                    matched.append(condition)
                continue

            if condition.code == DUOModifier.PROJECT_SPECIFIC.value:
                if condition.project and purpose.project != condition.project:
                    blocking.append(condition)
                else:
                    matched.append(condition)
                continue

            # For conditions not explicitly handled, mark as matched
            # (conservative: unknown conditions don't block)
            matched.append(condition)

        if blocking:
            return CompatibilityResult(
                compatible=False,
                reason=f"{len(blocking)} blocking condition(s) found",
                matched_conditions=matched if matched else None,
                blocking_conditions=blocking,
            )

        return CompatibilityResult(
            compatible=True,
            reason=f"All {len(matched)} condition(s) satisfied",
            matched_conditions=matched,
        )
