# src/fmatch/preprocessing/rules/phone_utils.py
from __future__ import annotations
import phonenumbers as pn
from typing import Dict, Any


def parse_phone(raw: str | None, region_hint: str | None = "US") -> Dict[str, str]:
    """
    Parse and normalize phone number with global region support.

    Args:
        raw: Raw phone number string
        region_hint: ISO country code for parsing context (e.g., "US", "JP", "KR", "DE")

    Returns:
        Dictionary with:
        - e164: E.164 formatted number (+15551234567)
        - national: National format ((555) 123-4567)
        - type: Phone number type (MOBILE, FIXED_LINE, VOIP, etc.)
    """
    if not raw:
        return {"e164": "", "national": "", "type": ""}

    try:
        # Parse phone number with region context
        num = pn.parse(raw, region_hint or None)

        # Skip validation for lenient parsing (many regional numbers appear "invalid")
        # if not pn.is_valid_number(num):
        #     raise ValueError("Invalid number")

        # Get number type
        ntype = pn.number_type(num)
        type_name = pn.PhoneNumberType._VALUES_TO_NAMES.get(ntype, "UNKNOWN")

        return {
            "e164": pn.format_number(num, pn.PhoneNumberFormat.E164),
            "national": pn.format_number(num, pn.PhoneNumberFormat.NATIONAL),
            "type": type_name,
        }
    except Exception:
        # Fallback: extract digits only
        digits = "".join(ch for ch in raw if ch.isdigit())
        return {"e164": "", "national": digits, "type": "UNKNOWN"}


def phone_is_strong(
    a: Dict[str, Any],
    b: Dict[str, Any],
    pa: Dict[str, str],
    pb: Dict[str, str],
    freq_map: Dict[str, int],
    max_freq: int = 2,
) -> bool:
    """
    Determine if phone number match is "strong" (high confidence anchor).

    Strong phone criteria:
    1. Same E.164 or national number
    2. Rare occurrence (frequency <= max_freq)
    3. Mobile/VOIP type (not shared landlines)

    Args:
        a, b: Record dictionaries
        pa, pb: Parsed phone dictionaries from parse_phone()
        freq_map: Frequency map of phone numbers
        max_freq: Maximum frequency to consider "rare"

    Returns:
        True if phone match should be considered strong evidence
    """
    # Must have same number
    same_e164 = pa["e164"] and pb["e164"] and pa["e164"] == pb["e164"]
    same_national = (
        pa["national"] and pb["national"] and pa["national"] == pb["national"]
    )

    if not (same_e164 or same_national):
        return False

    # Check frequency (rare numbers are stronger)
    phone_key = pa["e164"] or pa["national"]
    if not phone_key:
        return False

    frequency = freq_map.get(phone_key, 0)
    rare = frequency <= max_freq

    # Mobile/VOIP types are stronger than landlines
    is_mobile_type = pa["type"] in {"MOBILE", "VOIP", "PERSONAL_NUMBER"} or pb[
        "type"
    ] in {"MOBILE", "VOIP", "PERSONAL_NUMBER"}

    # Check for mobile phone fields in data
    has_mobile_field = (
        a.get("MobilePhone")
        or a.get("Mobile")
        or b.get("MobilePhone")
        or b.get("Mobile")
    )

    mobileish = is_mobile_type or has_mobile_field

    return same_e164 and rare and mobileish


# Regional phone number patterns for validation
REGIONAL_PATTERNS = {
    "US": r"^\+1[2-9]\d{9}$",
    "JP": r"^\+81[0-9]{1,4}[0-9]{4,8}$",
    "KR": r"^\+82[0-9]{1,4}[0-9]{3,8}$",
    "DE": r"^\+49[0-9]{2,5}[0-9]{3,12}$",
    "RU": r"^\+7[0-9]{10}$",
    "FR": r"^\+33[0-9]{9}$",
    "IT": r"^\+39[0-9]{6,11}$",
    "ES": r"^\+34[0-9]{9}$",
    "BR": r"^\+55[0-9]{10,11}$",
}
