from __future__ import annotations

import os
from typing import Any, Dict, List, Optional

from .company_domain_resolver import (
    resolve_company_domain,
    resolve_company_domains,
)


def company_to_domain(
    name: str,
    *,
    use_registry: bool = True,
    use_dns: Optional[bool] = None,
    use_llm: bool = False,
    max_candidates: int = 5,
    dns_timeout: float = 2.0,
    mode: Optional[str] = None,
    min_confidence: float = 0.60,
    use_wikidata: Optional[bool] = None,
    use_heuristics: Optional[bool] = None,
) -> Dict[str, Any]:
    """
    Backwards-compatible single-name resolution hook.

    V1 guardrails force registry-only mode and apply a minimum confidence
    threshold so the UI can rely on consistent behaviour.
    """
    # Enforce v1 guardrails regardless of caller input
    use_registry = True
    use_llm = False
    use_dns = False
    use_wikidata = True  # Enable Wikidata-backed lookup by default
    use_heuristics = True if use_heuristics is None else bool(use_heuristics)

    resolved_mode = _derive_mode(mode, use_dns)

    result = resolve_company_domain(
        name,
        mode=resolved_mode,
        use_registry=use_registry,
        use_llm=use_llm,
        allow_dns=False,
        use_wikidata=use_wikidata,
        use_heuristics=use_heuristics,
    )

    value = result.get("value") if isinstance(result, dict) else None
    if not isinstance(value, dict):
        value = {}
        if isinstance(result, dict):
            result["value"] = value
        else:
            result = {"value": value}

    # Preserve original confidence label while exposing numeric score for downstream use
    original_confidence = value.get("confidence")
    confidence_score = _coerce_confidence_score(value)
    value["confidence_score"] = confidence_score
    if original_confidence is None or isinstance(original_confidence, (int, float)):
        value["confidence"] = _score_to_label(confidence_score)

    if confidence_score < min_confidence:
        # Flag the low-confidence result but keep the candidate so users can review it
        meta = result.setdefault("meta", {})
        meta.update(
            {
                "reason": "confidence_below_threshold",
                "threshold": min_confidence,
                "actual_confidence": confidence_score,
            }
        )

    return result


def _coerce_confidence_score(value: Dict[str, Any]) -> float:
    """
    Convert legacy confidence payloads (high/medium/low) into numeric scores.
    """
    if "confidence_score" in value:
        try:
            return float(value["confidence_score"])
        except (TypeError, ValueError):
            pass

    raw = value.get("confidence")
    if isinstance(raw, (int, float)):
        return float(raw)
    if isinstance(raw, str):
        mapping = {"high": 0.95, "medium": 0.75, "low": 0.25}
        return mapping.get(raw.lower(), 0.0)
    return 0.0


def _score_to_label(score: float) -> str:
    if score >= 0.85:
        return "high"
    if score >= 0.6:
        return "medium"
    if score > 0:
        return "low"
    return ""


def resolve_company_to_domain_batch(
    names: List[str],
    *,
    mode: Optional[str] = None,
    use_registry: bool = True,
    use_llm: bool = False,
    use_dns: Optional[bool] = None,
    use_wikidata: Optional[bool] = None,
    use_heuristics: Optional[bool] = None,
) -> Dict[str, Any]:
    """
    Batch resolution with optional v1 guardrails.

    When called from Google Sheets or other v1 contexts, use_wikidata and use_heuristics
    should be False to enforce registry + hardcoded lookups only.
    """
    # Default to including Wikidata and heuristics can remain optional
    if use_wikidata is None:
        use_wikidata = True
    if use_heuristics is None:
        use_heuristics = False

    resolved_mode = _derive_mode(mode, use_dns)
    allow_dns = _allow_dns(resolved_mode, use_dns)
    values, metrics = resolve_company_domains(
        names,
        mode=resolved_mode,
        use_registry=use_registry,
        use_llm=use_llm,
        allow_dns=allow_dns,
        use_wikidata=use_wikidata,
        use_heuristics=use_heuristics,
    )
    return {"values": values, "metrics": metrics}


def _derive_mode(explicit_mode: Optional[str], use_dns: Optional[bool]) -> str:
    if explicit_mode:
        mode = explicit_mode.lower()
        if mode in {"fast", "balanced", "strict"}:
            return mode
    if use_dns is None:
        default_mode = (
            os.getenv("FM_COMPANY_TO_DOMAIN_DEFAULT_MODE", "fast") or "fast"
        ).lower()
        if default_mode not in {"fast", "balanced", "strict"}:
            default_mode = "fast"
        return default_mode
    return "strict" if use_dns else "fast"


def _allow_dns(mode: str, use_dns: Optional[bool]) -> Optional[bool]:
    if mode == "fast":
        return False
    if use_dns is not None:
        return bool(use_dns)
    env_dns = (os.getenv("FM_COMPANY_TO_DOMAIN_USE_DNS", "false") or "false").lower()
    if env_dns in {"true", "false"}:
        return env_dns == "true"
    return False
