# #region Test.DatasetReview.SemanticResolverEdge [C:3] [TYPE Module] [SEMANTICS test,semantic,resolver,fuzzy,match,edge]
# @BRIEF Edge-case coverage for semantic_resolver.py uncovered lines (149, 343, 347).
# @RELATION BINDS_TO -> [SemanticResolver]
# @TEST_EDGE: missing_mapping -> Returns empty when no mapping found
# @TEST_EDGE: invalid_type -> Non-string input handled gracefully
# @TEST_EDGE: empty_input -> Empty string returns no matches

from pathlib import Path
import sys

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

from unittest.mock import patch
import pytest


class TestSemanticSourceResolverEdge:
    """Cover fuzzy match and row processing edge cases."""

    @pytest.fixture
    def resolver(self):
        from src.services.dataset_review.semantic_resolver import SemanticSourceResolver
        return SemanticSourceResolver()

    def test_find_fuzzy_matches_with_empty_key(self, resolver):
        """Row with empty field_key is skipped (line 343)."""
        field_name = "region"
        rows = [
            {"field_key": "", "field_name": "Empty"},
            {"field_key": "region", "field_name": "Region"},
        ]
        result = resolver._find_fuzzy_matches(field_name, rows)
        assert len(result) >= 1
        # The empty key row should be skipped, only region matches

    def test_find_fuzzy_matches_low_score_skipped(self, resolver):
        """Row with score below 0.72 is skipped (line 347)."""
        field_name = "region"
        rows = [
            {"field_key": "completely_different_name", "field_name": "Different"},
        ]
        result = resolver._find_fuzzy_matches(field_name, rows)
        assert len(result) == 0

    def test_find_fuzzy_matches_good_score(self, resolver):
        """Row with score above 0.72 is included."""
        # Use strings close enough to exceed 0.72 threshold
        field_name = "salesregion"
        rows = [
            {"field_key": "sales_region", "field_name": "Sales Region"},
        ]
        result = resolver._find_fuzzy_matches(field_name, rows)
        assert len(result) >= 1
        assert result[0]["score"] >= 0.72

    def test_find_fuzzy_matches_top_3(self, resolver):
        """Only top 3 fuzzy matches returned."""
        field_name = "sales_amount_value"
        rows = [
            {"field_key": f"sales_amount_{i}" if i < 5 else "unrelated", "field_name": f"Sales {i}"}
            for i in range(10)
        ]
        result = resolver._find_fuzzy_matches(field_name, rows)
        assert len(result) <= 3

    def test_resolve_from_dictionary_no_matches(self, resolver):
        """Field with no dictionary match produces unresolved entry."""
        source_payload = {
            "source_ref": "test_dict",
            "rows": [
                {"field_name": "Region"},
                {"field_name": "Country"},
            ],
        }
        fields = [{"field_name": "nonexistent_field"}]

        result = resolver.resolve_from_dictionary(source_payload, fields)
        assert result.unresolved_fields == ["nonexistent_field"]
        assert len(result.resolved_fields) == 1
        assert result.resolved_fields[0]["status"] == "unresolved"

    def test_normalize_dictionary_row(self, resolver):
        """_normalize_dictionary_row produces expected keys."""
        row = {"field_name": "My Field", "verbose_name": "My Field Label"}
        result = resolver._normalize_dictionary_row(row)
        assert result["field_key"] == "myfield"  # normalized: lowercase, no spaces
        assert result["field_name"] == "My Field"

    def test_resolve_from_dictionary_fuzzy_match(self, resolver):
        """Fuzzy match produces ranked candidates (coverage for line 149)."""
        source_payload = {
            "source_ref": "test_dict",
            "rows": [
                {"field_name": "Sales Amount"},
                {"field_name": "Revenue"},
            ],
        }
        # Use a field name close enough to "sales amount"
        fields = [{"field_name": "sales_amount"}]

        result = resolver.resolve_from_dictionary(source_payload, fields)
        assert len(result.resolved_fields) == 1
        assert result.resolved_fields[0]["field_name"] == "sales_amount"
        candidates = result.resolved_fields[0].get("candidates", [])
        # Should have at least one candidate (exact or fuzzy)
        assert len(candidates) >= 1

    def test_resolve_from_dictionary_locked_field(self, resolver):
        """Locked field is preserved."""
        source_payload = {
            "source_ref": "test_dict",
            "rows": [
                {"field_name": "Region"},
            ],
        }
        fields = [{"field_name": "region", "is_locked": True}]

        result = resolver.resolve_from_dictionary(source_payload, fields)
        assert result.resolved_fields[0].get("is_locked") is True
# #endregion Test.DatasetReview.SemanticResolverEdge
