"""Master-controlled feature entitlements + business analytics module toggles per BID."""

from __future__ import annotations

from typing import Any, Dict, Optional, Tuple

# (allow_key, label) — master plan / upgrade gate
ENTITLEMENT_SPECS: Tuple[Tuple[str, str], ...] = (
    ("allow_quality_scoring", "Quality Scoring"),
    ("allow_sentiment", "Customer Sentiment"),
    ("allow_talk_listen_ratio", "Talk/Listen Ratio"),
    ("allow_data_capture", "Data Capture Points"),
    ("allow_path_to_conversion", "Path to Conversion"),
    ("allow_min_duration_filter", "Min Duration Filter"),
    ("allow_propensity", "Sales Propensity"),
    ("allow_call_summary", "Call Summary"),
    ("allow_group_filter", "Group Filter"),
    ("allow_crm_integration", "CRM Integration"),
)

ENTITLEMENT_KEYS = tuple(key for key, _ in ENTITLEMENT_SPECS)

# (enable_key, allow_key, label) — business activation in Settings
MODULE_SPECS: Tuple[Tuple[str, str, str], ...] = (
    ("quality_scoring_enabled", "allow_quality_scoring", "Quality Scoring"),
    ("sentiment_enabled", "allow_sentiment", "Customer Sentiment"),
    ("talk_listen_enabled", "allow_talk_listen_ratio", "Talk/Listen Ratio"),
    ("data_capture_enabled", "allow_data_capture", "Data Capture Points"),
    ("path_to_conversion_enabled", "allow_path_to_conversion", "Path to Conversion"),
    ("min_duration_filter_enabled", "allow_min_duration_filter", "Min Duration Filter"),
    ("propensity_enabled", "allow_propensity", "Sales Propensity"),
    ("call_summary_enabled", "allow_call_summary", "Call Summary Style"),
)

MODULE_ENABLE_KEYS = tuple(spec[0] for spec in MODULE_SPECS)

ALLOW_TO_ENABLE = {allow_key: enable_key for enable_key, allow_key, _ in MODULE_SPECS}

UPGRADE_MESSAGES = {
    "allow_quality_scoring": (
        "Quality scoring is not enabled for your account. "
        "Contact your PCA administrator to upgrade this feature."
    ),
    "allow_sentiment": (
        "Customer sentiment analysis is not enabled for your account. "
        "Contact your PCA administrator to upgrade this feature."
    ),
    "allow_talk_listen_ratio": (
        "Talk/listen ratio is not enabled for your account. "
        "Contact your PCA administrator to upgrade this feature."
    ),
    "allow_data_capture": (
        "Data capture points are not enabled for your account. "
        "Contact your PCA administrator to upgrade this feature."
    ),
    "allow_path_to_conversion": (
        "Path to conversion insights are not enabled for your account. "
        "Contact your PCA administrator to upgrade this feature."
    ),
    "allow_min_duration_filter": (
        "Minimum call duration filtering is not enabled for your account. "
        "Contact your PCA administrator to upgrade this feature."
    ),
    "allow_propensity": (
        "Sales Propensity is not enabled for your account. "
        "Contact your PCA administrator to upgrade this feature."
    ),
    "allow_call_summary": (
        "Call summaries are not enabled for your account. "
        "Contact your PCA administrator to upgrade this feature."
    ),
    "allow_group_filter": (
        "Group filtering is not enabled for your account. "
        "Contact your PCA administrator to upgrade this feature."
    ),
    "allow_crm_integration": (
        "CRM integration is not enabled for your account. "
        "Contact your PCA administrator to upgrade this feature."
    ),
}

DEFAULT_ENTITLEMENTS = {key: True for key in ENTITLEMENT_KEYS}
DEFAULT_MODULES = {key: True for key in MODULE_ENABLE_KEYS}


def _as_bool(value: Any, default: bool = True) -> bool:
    if value is None:
        return default
    if isinstance(value, bool):
        return value
    if isinstance(value, (int, float)):
        return bool(int(value))
    text = str(value).strip().lower()
    if text in {"1", "true", "yes", "on"}:
        return True
    if text in {"0", "false", "no", "off"}:
        return False
    return default


def extract_entitlements(cfg: Optional[Dict[str, Any]] = None) -> Dict[str, bool]:
    cfg = cfg or {}
    return {key: _as_bool(cfg.get(key), DEFAULT_ENTITLEMENTS[key]) for key in ENTITLEMENT_KEYS}


def extract_modules(cfg: Optional[Dict[str, Any]] = None) -> Dict[str, bool]:
    """Business-side module toggles (defaults ON — preserves legacy behavior)."""
    cfg = cfg or {}
    return {key: _as_bool(cfg.get(key), DEFAULT_MODULES[key]) for key in MODULE_ENABLE_KEYS}


def effective_modules(cfg: Optional[Dict[str, Any]] = None) -> Dict[str, bool]:
    """True only when master allowed AND business enabled."""
    cfg = cfg or {}
    entitlements = extract_entitlements(cfg)
    modules = extract_modules(cfg)
    effective: Dict[str, bool] = {}
    for enable_key, allow_key, _label in MODULE_SPECS:
        effective[enable_key] = entitlements.get(allow_key, True) and modules.get(enable_key, True)
    return effective


def module_active(cfg: Optional[Dict[str, Any]], enable_key: str) -> bool:
    return effective_modules(cfg).get(enable_key, True)


def parse_entitlement_updates(payload: Optional[Dict[str, Any]] = None) -> Dict[str, bool]:
    payload = payload or {}
    updates: Dict[str, bool] = {}
    for key in ENTITLEMENT_KEYS:
        if key in payload:
            updates[key] = _as_bool(payload[key], False)
    return updates


def parse_module_updates(payload: Optional[Dict[str, Any]] = None) -> Dict[str, bool]:
    payload = payload or {}
    updates: Dict[str, bool] = {}
    for key in MODULE_ENABLE_KEYS:
        if key in payload:
            updates[key] = _as_bool(payload[key], False)
    return updates


def upgrade_message(key: str) -> str:
    return UPGRADE_MESSAGES.get(
        key,
        "This feature is not enabled for your account. Contact your PCA administrator to upgrade.",
    )


def entitlement_allowed(cfg: Optional[Dict[str, Any]], key: str) -> bool:
    return extract_entitlements(cfg).get(key, True)


def require_entitlement(cfg: Optional[Dict[str, Any]], key: str) -> None:
    from fastapi import HTTPException

    if not entitlement_allowed(cfg, key):
        raise HTTPException(status_code=403, detail=upgrade_message(key))


def _require_module_allowed(cfg: Optional[Dict[str, Any]], enable_key: str) -> None:
    from fastapi import HTTPException

    allow_key = None
    for spec_enable, spec_allow, _ in MODULE_SPECS:
        if spec_enable == enable_key:
            allow_key = spec_allow
            break
    if allow_key and not entitlement_allowed(cfg, allow_key):
        raise HTTPException(status_code=403, detail=upgrade_message(allow_key))


def validate_modules_update(
    cfg: Optional[Dict[str, Any]],
    data: Dict[str, Any],
    *,
    is_master: bool = False,
) -> None:
    if is_master:
        return
    entitlements = extract_entitlements(cfg)
    for enable_key, allow_key, _ in MODULE_SPECS:
        if data.get(enable_key) in (True, 1, "1") and not entitlements.get(allow_key, True):
            from fastapi import HTTPException

            raise HTTPException(status_code=403, detail=upgrade_message(allow_key))


def validate_pipeline_config_update(
    cfg: Optional[Dict[str, Any]],
    data: Dict[str, Any],
    *,
    is_master: bool = False,
) -> None:
    """Block business users from enabling features their plan does not include."""
    if is_master:
        return
    validate_modules_update(cfg, data, is_master=False)
    entitlements = extract_entitlements(cfg)
    if data.get("group_filter_enabled") in (True, 1, "1") and not entitlements["allow_group_filter"]:
        from fastapi import HTTPException

        raise HTTPException(status_code=403, detail=upgrade_message("allow_group_filter"))
    if data.get("min_duration_filter_enabled") in (True, 1, "1") and not entitlements[
        "allow_min_duration_filter"
    ]:
        from fastapi import HTTPException

        raise HTTPException(status_code=403, detail=upgrade_message("allow_min_duration_filter"))


def validate_summary_config_update(
    cfg: Optional[Dict[str, Any]],
    summary_mode: str,
    *,
    is_master: bool = False,
) -> None:
    if is_master:
        return
    from summary_config import normalize_summary_mode

    mode = normalize_summary_mode(summary_mode)
    entitlements = extract_entitlements(cfg)
    if mode != "default" and not entitlements.get("allow_call_summary", True):
        from fastapi import HTTPException

        raise HTTPException(status_code=403, detail=upgrade_message("allow_call_summary"))


def side_effects_for_entitlement_changes(
    current: Dict[str, bool],
    updates: Dict[str, bool],
    *,
    current_summary_mode: str = "default",
) -> Dict[str, Any]:
    """When master revokes entitlements, turn off dependent business settings."""
    from summary_config import normalize_summary_mode

    merged = {**current, **updates}
    patch: Dict[str, Any] = {}
    for allow_key, enable_key in ALLOW_TO_ENABLE.items():
        if current.get(allow_key) and not merged.get(allow_key):
            patch[enable_key] = 0
    if current.get("allow_group_filter") and not merged.get("allow_group_filter"):
        patch["group_filter_enabled"] = 0
        patch["allowed_groupnames"] = []
    mode = normalize_summary_mode(current_summary_mode)
    if current.get("allow_call_summary") and not merged.get("allow_call_summary"):
        if mode != "default":
            patch["summary_mode"] = "default"
            patch["summary_instructions"] = None
        patch["allow_custom_summary"] = 0
        patch["allow_discovery_recap_summary"] = 0
    elif "allow_call_summary" in updates:
        summary_allowed = bool(merged.get("allow_call_summary"))
        patch["allow_custom_summary"] = 1 if summary_allowed else 0
        patch["allow_discovery_recap_summary"] = 1 if summary_allowed else 0
    return patch
