from __future__ import annotations

from typing import Any, Dict, List


def _as_list(value: Any) -> list[str]:
    if isinstance(value, list):
        return [str(item or "").strip().upper() for item in value if str(item or "").strip()]
    return []


def evaluate_strategy_market_fit(
    strategy_contract: Dict[str, Any],
    canonical_market_snapshot: Dict[str, Any],
) -> Dict[str, Any]:
    contract = strategy_contract if isinstance(strategy_contract, dict) else {}
    snapshot = canonical_market_snapshot if isinstance(canonical_market_snapshot, dict) else {}
    normalized = snapshot.get("normalized", {}) if isinstance(snapshot.get("normalized", {}), dict) else {}

    market_family = str(normalized.get("market_family", "TRANSITION") or "TRANSITION").upper()
    market_phase = str(normalized.get("market_phase", "TRANSITION") or "TRANSITION").upper()
    entry_family = str(normalized.get("entry_family", "hold") or "hold").lower()
    session_bucket = str(normalized.get("session_bucket", "UNKNOWN") or "UNKNOWN").upper()
    volatility_state = str(normalized.get("volatility_state", "NORMAL") or "NORMAL").upper()
    regime_confidence = float(normalized.get("confidence", 0.0) or 0.0)

    family_tags = _as_list(contract.get("market_family_tags"))
    phase_tags = _as_list(contract.get("market_phase_tags"))
    entry_tags = [item.lower() for item in _as_list(contract.get("entry_family_tags"))]
    allowed_regimes = _as_list(contract.get("applicable_regimes"))
    session_tags = _as_list(contract.get("session_tags"))
    volatility_tags = _as_list(contract.get("volatility_tags"))
    min_confidence = float(contract.get("min_market_confidence", 0.0) or 0.0)
    min_regime_confidence = float(contract.get("min_regime_confidence", min_confidence) or min_confidence)

    reasons: List[str] = []
    score = 0.0
    eligible = True
    transition_market = market_family == "TRANSITION"
    transition_entry = transition_market and entry_family == "hold"
    transition_supported = transition_market and "TRANSITION" in set(allowed_regimes)

    if family_tags:
        if market_family in family_tags:
            score += 0.40
            reasons.append(f"market_family_match:{market_family}")
        elif transition_market and bool({"TREND", "RANGE", "RANGING", "TRANSITION"} & set(family_tags)):
            score += 0.20
            reasons.append("market_family_transition_soft_match")
        else:
            eligible = False
            reasons.append(f"market_family_mismatch:{market_family}")

    if phase_tags:
        if market_phase in phase_tags:
            score += 0.20
            reasons.append(f"market_phase_match:{market_phase}")
        else:
            reasons.append(f"market_phase_soft_mismatch:{market_phase}")

    if entry_tags:
        if entry_family in entry_tags:
            score += 0.15
            reasons.append(f"entry_family_match:{entry_family}")
        elif transition_entry and bool({"trend", "range", "hold"} & set(entry_tags)):
            score += 0.05
            reasons.append("entry_family_transition_soft_match")
        else:
            eligible = False
            reasons.append(f"entry_family_mismatch:{entry_family}")

    if session_tags:
        if "ALL" in session_tags or session_bucket in session_tags:
            score += 0.10
            reasons.append(f"session_match:{session_bucket}")
        else:
            reasons.append(f"session_soft_mismatch:{session_bucket}")
            score -= 0.05

    if volatility_tags:
        if volatility_state in volatility_tags:
            score += 0.10
            reasons.append(f"volatility_match:{volatility_state}")
        else:
            reasons.append(f"volatility_soft_mismatch:{volatility_state}")
            score -= 0.05

    required_confidence = min_confidence
    if transition_supported:
        required_confidence = min(min_confidence, min_regime_confidence)
        reasons.append(f"transition_confidence_floor:{required_confidence:.2f}")

    if regime_confidence >= required_confidence:
        score += 0.05
        reasons.append(f"confidence_pass:{regime_confidence:.2f}")
    else:
        eligible = False
        reasons.append(f"confidence_low:{regime_confidence:.2f}")

    fit_score = max(0.0, min(1.0, round(score, 4)))
    return {
        "strategy_id": str(contract.get("strategy_id", "") or ""),
        "eligible": bool(eligible),
        "fit_score": fit_score,
        "market_family": market_family,
        "entry_family": entry_family,
        "reasons": reasons,
    }
