# saas/services/confidence_scorer.py

"""
Confidence scoring and explanation system for matches.
Makes scores explainable and trustworthy.
"""

from typing import Dict, Any

# NOTE: fuzzy similarity handled via engine/intelligence layer
import asyncio

# NEW:
from .engine_client import get_engine_client


class ConfidenceScorer:
    """Calculates and explains match confidence."""

    @staticmethod
    async def score_match_async(
        record1: Dict[str, Any], record2: Dict[str, Any], weights: Dict[str, float]
    ) -> Dict[str, Any]:
        """
        Score a match using the core engine, but keep the same output shape.
        """
        eng = get_engine_client()

        # Translate weights -> engine mappings
        mappings = []
        for field, weight in (weights or {}).items():
            f = field.lower()
            algo = "TokenSetRatio"
            if any(x in f for x in ("email", "phone", "id")):
                algo = "Exact"
            if any(x in f for x in ("website", "domain", "url")):
                # If your engine supports Domain, prefer it. Otherwise Exact on preprocessed domain columns.
                algo = "Domain"
            mappings.append(
                {
                    "source_column": field,
                    "reference_column": field,
                    "weight": float(weight or 1.0),
                    "algorithm": algo,
                }
            )

        res = await eng.score_pair(record1, record2, mappings=mappings)

        # Build the same payload your callers expect
        percent = res.get("confidence_percent", int(res.get("score", 0) * 100))
        field_scores = res.get("field_scores", {})

        matching_fields = []
        for k, v in field_scores.items():
            if v >= 0.95:
                matching_fields.append((k, "exact"))
            elif v > 0:
                matching_fields.append((k, f"{int(v*100)}%"))

        return {
            "score": res.get("score", 0.0),
            "confidence_percent": percent,
            "tier": res.get("tier")
            or ConfidenceScorer._get_confidence_tier(res.get("score", 0.0)),
            "contributions": {
                k: round(v * weights.get(k, 1.0), 3) for k, v in field_scores.items()
            },
            "explanation": res.get("explanation") or "Engine-derived similarity",
            "visual": ConfidenceScorer._format_visual_bar(percent),
            "matching_fields": matching_fields,
        }

    # Back-compat shim if some code still calls the sync version
    @staticmethod
    def score_match(
        record1: Dict[str, Any], record2: Dict[str, Any], weights: Dict[str, float]
    ) -> Dict[str, Any]:
        return asyncio.get_event_loop().run_until_complete(
            ConfidenceScorer.score_match_async(record1, record2, weights)
        )

    # keep your tier + bar helpers as-is:
    @staticmethod
    def _get_confidence_tier(score: float) -> str:
        if score >= 0.95:
            return "CERTAIN"
        if score >= 0.85:
            return "LIKELY"
        if score >= 0.75:
            return "POSSIBLE"
        if score >= 0.65:
            return "REVIEW"
        return "UNLIKELY"

    @staticmethod
    def _format_visual_bar(percent: int) -> str:
        filled = int(percent / 10)
        empty = 10 - filled
        return f"[{'█' * filled}{'░' * empty}] {percent}%"

    @staticmethod
    def explain_tier(tier: str) -> Dict[str, Any]:
        """Get detailed explanation for a confidence tier."""
        tiers = {
            "CERTAIN": {
                "color": "#10B981",
                "icon": "✓✓",
                "message": "Definitely the same record",
                "action": "Safe to merge automatically",
            },
            "LIKELY": {
                "color": "#3B82F6",
                "icon": "✓",
                "message": "Very likely the same record",
                "action": "Review recommended before merge",
            },
            "POSSIBLE": {
                "color": "#F59E0B",
                "icon": "?",
                "message": "Possibly the same record",
                "action": "Manual review required",
            },
            "REVIEW": {
                "color": "#6B7280",
                "icon": "👁",
                "message": "Needs review",
                "action": "Manual inspection needed",
            },
            "UNLIKELY": {
                "color": "#EF4444",
                "icon": "✗",
                "message": "Probably different records",
                "action": "Should not be merged",
            },
        }
        return tiers.get(tier, tiers["REVIEW"])
