import logging
from typing import Optional
from twilio.rest import Client
from django.conf import settings
from apps.core.services.secret_manager import SecretManager

logger = logging.getLogger(__name__)
_twilio_api_client = None
_twilio_client = None
_twilio_sms_client = None
_HAS_LOOKUPS_V2 = None

TWILIO_FROM_NUMBER = settings.TWILIO_FROM_NUMBER


class TwilioConfigService:

    @staticmethod
    def account_sid():
        return SecretManager.get("TWILIO_ACCOUNT_SID")

    @staticmethod
    def auth_token():
        return SecretManager.get("TWILIO_AUTH_TOKEN")

    @staticmethod
    def api_key_sid():
        return SecretManager.get("TWILIO_API_KEY_SID")

    @staticmethod
    def api_key_secret():
        return SecretManager.get("TWILIO_API_KEY_SECRET")


def get_twilio_credentials():
    return TwilioConfigService.account_sid(), TwilioConfigService.auth_token()


def get_twilio_api_client() -> Client:
    """Return a singleton Twilio API client using Django settings."""
    global _twilio_api_client, _HAS_LOOKUPS_V2
    if _twilio_api_client is None:
        _twilio_api_client = Client(
            TwilioConfigService.api_key_sid(),
            TwilioConfigService.api_key_secret(),
            TwilioConfigService.account_sid(),
        )

        try:
            _HAS_LOOKUPS_V2 = hasattr(_twilio_api_client.lookups, "v2")
            logger.info(f"Twilio Lookups v2 supported: {_HAS_LOOKUPS_V2}")
        except Exception as exc:
            _HAS_LOOKUPS_V2 = False
            logger.warning(f"Unable to detect Twilio Lookups v2 support {exc}")
    return _twilio_api_client


def get_twilio_client() -> Client:
    """Return a singleton Twilio client using Django settings."""
    global _twilio_client
    if _twilio_client is None:
        _twilio_client = Client(
            TwilioConfigService.account_sid(),
            TwilioConfigService.auth_token(),
        )
    return _twilio_client


def get_caller_name_by_phone_number(phone_number: str) -> Optional[str]:
    """
    Retrieve phone number owner name from Twilio

    Args:
        phone_number: The phone number in E.164 format

    Returns:
        A string containing name
    """
    if not phone_number or not phone_number.strip():
        return None

    client = get_twilio_api_client()

    if _HAS_LOOKUPS_V2:
        try:
            lookup_result = (
                client.lookups.v2.phone_numbers(phone_number)
                .fetch(fields=["caller_name"])
            )

            caller_name_data = getattr(lookup_result, "caller_name", None)

            if isinstance(caller_name_data, dict):
                name = caller_name_data.get("caller_name")
                if name and "unknown" not in name.lower():
                    return name.strip()

            return None

        except Exception as exc:
            logger.warning(f"Twilio Lookups v2 failed, falling back to v1: {exc}")

    try:
        lookup_result = (
            client.lookups.phone_numbers(phone_number)
            .fetch(type=["caller-name"])
        )

        caller_name_data = getattr(lookup_result, "caller_name", None)

        if isinstance(caller_name_data, dict):
            name = caller_name_data.get("caller_name")
            if name and "unknown" not in name.lower():
                return name.strip()

    except Exception as exc:
        logger.warning(f"Twilio lookup failed for both v2 and v1: {exc}")

    return None
