# #region Test.Assistant.DatasetReviewExtended [C:2] [TYPE Module] [SEMANTICS test,assistant,dataset,review,edge]
# @BRIEF Edge-case coverage for _dataset_review.py and _dataset_review_dispatch.py uncovered lines.
# @RELATION BINDS_TO -> [AssistantDatasetReview]
# @RELATION BINDS_TO -> [AssistantDatasetReviewDispatch]

from pathlib import Path
import sys

sys.path.insert(0, str(Path(__file__).parent.parent / "src"))

from datetime import UTC, datetime
from unittest.mock import MagicMock, AsyncMock, patch
import pytest
from fastapi import HTTPException


class TestMatchDatasetReviewFieldExtended:
    """_match_dataset_review_field — field_name and verbose_name matching paths."""

    def test_match_by_field_name(self):
        from src.api.routes.assistant._dataset_review import _match_dataset_review_field

        ctx = {"semantic_fields": [{"field_id": "fld-1", "field_name": "region", "verbose_name": "Region"}]}
        result = _match_dataset_review_field(ctx, "update the region field please")
        assert result is not None
        assert result["field_name"] == "region"

    def test_match_by_verbose_name(self):
        from src.api.routes.assistant._dataset_review import _match_dataset_review_field

        ctx = {"semantic_fields": [{"field_id": "fld-1", "field_name": "rgn", "verbose_name": "Region Name"}]}
        result = _match_dataset_review_field(ctx, "change Region Name")
        assert result is not None
        assert result["verbose_name"] == "Region Name"

    def test_match_by_field_id_lowercase_in_message(self):
        """Match field when field_id appears in message text."""
        from src.api.routes.assistant._dataset_review import _match_dataset_review_field

        ctx = {"semantic_fields": [{"field_id": "FLD-001", "field_name": "sales", "verbose_name": "Sales"}]}
        # field_id "fld-001" does not appear in message — should try field_name/verbose
        result = _match_dataset_review_field(ctx, "about sales data")
        assert result is not None
        assert result["field_name"] == "sales"


class TestPlanDatasetReviewIntentExtended:
    """_plan_dataset_review_intent — uncovered branches."""

    @pytest.fixture
    def context(self):
        return {
            "session_id": "sess-1",
            "version": 5,
            "readiness_state": "REVIEW_READY",
            "recommended_action": "REVIEW_DOCUMENTATION",
            "mappings": [],
            "findings": [{"code": "TEST"}],
            "imported_filters": [{"filter_name": "region"}],
            "preview": {"preview_status": "missing"},
            "semantic_fields": [
                {
                    "field_id": "fld-1",
                    "field_name": "region",
                    "verbose_name": "Region",
                    "candidates": [{"candidate_id": "cand-1"}],
                }
            ],
        }

    def test_set_field_semantics_accept_candidate(self, context):
        """Accept first candidate via message keywords."""
        from src.api.routes.assistant._dataset_review import _plan_dataset_review_intent
        result = _plan_dataset_review_intent(
            'apply field semantics target:field=fld-1 accept candidate',
            context,
        )
        assert result is not None
        assert result["operation"] == "dataset_review_set_field_semantics"
        assert result["entities"]["candidate_id"] == "cand-1"

    def test_set_field_semantics_with_label(self, context):
        """Set verbose_name via 'label' keyword (matches regex alternation)."""
        from src.api.routes.assistant._dataset_review import _plan_dataset_review_intent
        result = _plan_dataset_review_intent(
            'set field semantics target:field=fld-1 label="Country"',
            context,
        )
        assert result is not None
        assert result["entities"]["verbose_name"] == "Country"

    def test_set_field_semantics_with_description(self, context):
        """Set description via 'desc' keyword."""
        from src.api.routes.assistant._dataset_review import _plan_dataset_review_intent
        result = _plan_dataset_review_intent(
            'set field semantics target:field=fld-1 desc="The country field"',
            context,
        )
        assert result is not None
        assert result["entities"]["description"] == "The country field"

    def test_set_field_semantics_no_attributes_returns_none(self, context):
        """No candidate, verbose_name, description, or display_format returns None."""
        from src.api.routes.assistant._dataset_review import _plan_dataset_review_intent
        result = _plan_dataset_review_intent(
            'set field semantics target:field=fld-1',
            context,
        )
        assert result is None

    def test_set_field_semantics_with_lock(self, context):
        """Lock field when message contains lock keywords."""
        from src.api.routes.assistant._dataset_review import _plan_dataset_review_intent
        result = _plan_dataset_review_intent(
            'update semantic field target:field=fld-1 lock it desc="Locked"',
            context,
        )
        assert result is not None
        assert result["entities"]["lock_field"] is True


class TestDispatchDatasetReviewIntentExtended:
    """_dispatch_dataset_review_intent — uncovered branches."""

    @pytest.fixture
    def user(self):
        from src.schemas.auth import User
        return User(id="user-1", username="test", email="test@x.com", is_active=True,
                    auth_source="internal", created_at=datetime.now(UTC),
                    last_login=datetime.now(UTC), roles=[])

    @pytest.fixture
    def config_manager(self):
        cm = MagicMock()
        cm.get_environments = MagicMock(return_value=[])
        return cm

    def _make_session_mock(self, **overrides):
        from src.models.dataset_review import ReadinessState, RecommendedAction, SessionStatus, SessionPhase
        s = MagicMock()
        s.session_id = overrides.get("session_id", "sess-1")
        s.version = overrides.get("version", 5)
        s.user_id = overrides.get("user_id", "user-1")
        s.readiness_state = overrides.get("readiness_state",
                                           MagicMock(value=ReadinessState.MAPPING_REVIEW_NEEDED.value))
        s.recommended_action = overrides.get("recommended_action",
                                              MagicMock(value=RecommendedAction.REVIEW_DOCUMENTATION.value))
        s.execution_mappings = overrides.get("execution_mappings", [])
        s.semantic_fields = overrides.get("semantic_fields", [])
        s.last_activity_at = None
        return s

    def _make_mapping_mock(self, **overrides):
        from src.models.dataset_review import ApprovalState
        m = MagicMock()
        m.mapping_id = overrides.get("mapping_id", "m-1")
        m.approval_state = overrides.get("approval_state", ApprovalState.PENDING)
        m.requires_explicit_approval = overrides.get("requires_explicit_approval", True)
        return m

    def _make_field_mock(self, **overrides):
        f = MagicMock()
        f.field_id = overrides.get("field_id", "fld-1")
        f.field_name = overrides.get("field_name", "region")
        return f

    def test_approve_mappings_updates_readiness_state(self, user, config_manager):
        """When MAPPING_REVIEW_NEEDED, recommended_action changes to GENERATE_SQL_PREVIEW."""
        from src.api.routes.assistant._dataset_review_dispatch import _dispatch_dataset_review_intent
        from src.models.dataset_review import ApprovalState

        mapping = self._make_mapping_mock(mapping_id="m-1", approval_state=ApprovalState.PENDING,
                                           requires_explicit_approval=True)
        session = self._make_session_mock(execution_mappings=[mapping], user_id="user-1")

        intent = {
            "operation": "dataset_review_approve_mappings",
            "entities": {
                "dataset_review_session_id": "sess-1",
                "session_version": 5,
                "mapping_ids": ["m-1"],
            },
        }

        db = MagicMock()
        with patch("src.api.routes.assistant._dataset_review_dispatch.DatasetReviewSessionRepository") as mock_repo_cls:
            mock_repo = MagicMock()
            mock_repo_cls.return_value = mock_repo
            mock_repo.load_session_detail.return_value = session
            mock_repo.require_session_version.return_value = None
            mock_repo.bump_session_version.return_value = None
            mock_repo.db = MagicMock()
            mock_repo.event_logger = MagicMock()

            text, task_id, actions = (
                __import__("asyncio").run(_dispatch_dataset_review_intent(intent, user, config_manager, db))
            )
            assert "Approved" in text

    def test_set_field_semantics_value_error(self, user, config_manager):
        """ValueError from _update_semantic_field_state becomes 400."""
        from src.api.routes.assistant._dataset_review_dispatch import _dispatch_dataset_review_intent

        field = self._make_field_mock()
        session = self._make_session_mock(semantic_fields=[field], user_id="user-1")

        intent = {
            "operation": "dataset_review_set_field_semantics",
            "entities": {
                "dataset_review_session_id": "sess-1",
                "session_version": 5,
                "field_id": "fld-1",
                "lock_field": True,
            },
        }

        db = MagicMock()
        with patch("src.api.routes.assistant._dataset_review_dispatch.DatasetReviewSessionRepository") as mock_repo_cls:
            mock_repo = MagicMock()
            mock_repo_cls.return_value = mock_repo
            mock_repo.load_session_detail.return_value = session
            mock_repo.require_session_version.return_value = None

            with patch("src.api.routes.assistant._dataset_review_dispatch._update_semantic_field_state",
                       side_effect=ValueError("Invalid field value")):
                with pytest.raises(HTTPException) as exc:
                    __import__("asyncio").run(
                        _dispatch_dataset_review_intent(intent, user, config_manager, db)
                    )
                assert exc.value.status_code == 400
                assert "Invalid" in str(exc.value.detail)

    def test_set_field_semantics_field_not_found(self, user, config_manager):
        """Field not found in session raises 404."""
        from src.api.routes.assistant._dataset_review_dispatch import _dispatch_dataset_review_intent

        session = self._make_session_mock(semantic_fields=[], user_id="user-1")

        intent = {
            "operation": "dataset_review_set_field_semantics",
            "entities": {
                "dataset_review_session_id": "sess-1",
                "session_version": 5,
                "field_id": "nonexistent",
            },
        }

        db = MagicMock()
        with patch("src.api.routes.assistant._dataset_review_dispatch.DatasetReviewSessionRepository") as mock_repo_cls:
            mock_repo = MagicMock()
            mock_repo_cls.return_value = mock_repo
            mock_repo.load_session_detail.return_value = session
            mock_repo.require_session_version.return_value = None

            with pytest.raises(HTTPException) as exc:
                __import__("asyncio").run(
                    _dispatch_dataset_review_intent(intent, user, config_manager, db)
                )
            assert exc.value.status_code == 404
# #endregion Test.Assistant.DatasetReviewExtended
