import logging
import time
from typing import TYPE_CHECKING, Any, Dict, List

import httpx

from src.core.config import settings

if TYPE_CHECKING:
    from src.group_settings.models import GroupConfig

logger = logging.getLogger(__name__)

# Per-group in-memory cache: group_email -> (events_list, cache_timestamp)
_events_cache: Dict[str, tuple[List[Dict[str, Any]], float]] = {}
_CACHE_TTL = 300  # 5 minutes


def _resolve_token(group_config: "GroupConfig | None") -> str:
    """Return the Campflow API token for the given group, falling back to env."""
    if group_config and group_config.campflow_api_token_enc:
        from src.core.encryption import decrypt
        try:
            return decrypt(group_config.campflow_api_token_enc)
        except ValueError:
            logger.error("Failed to decrypt Campflow API token for group %s", 
                         group_config.group_email if group_config else "unknown")
    return settings.api_auth_token


def _cache_key(group_config: "GroupConfig | None") -> str:
    return group_config.group_email if group_config else "__global__"


class CampflowClient:
    def __init__(self, auth_token: str, cache_key: str = "__global__"):
        self.base_url = settings.api_base_url.rstrip("/")
        self.auth_token = auth_token
        self._cache_key = cache_key

    def _get_headers(self) -> Dict[str, str]:
        return {
            "Authorization": f"Bearer {self.auth_token}",
            "Accept": "application/json",
        }

    async def get_events(self, force_refresh: bool = False) -> List[Dict[str, Any]]:
        """Fetches all events from the Campflow API. Caches per group for 5 minutes."""
        if not self.auth_token:
            logger.error("Campflow API token is missing.")
            return []

        current_time = time.time()
        cached = _events_cache.get(self._cache_key)
        if not force_refresh and cached:
            events, ts = cached
            if (current_time - ts) < _CACHE_TTL:
                return events

        url = f"{self.base_url}/events"
        try:
            async with httpx.AsyncClient() as client:
                response = await client.get(url, headers=self._get_headers(), timeout=10.0)
                response.raise_for_status()
                events = response.json().get("data", [])
                _events_cache[self._cache_key] = (events, time.time())
                return events
        except httpx.HTTPError as e:
            logger.error(f"HTTPError fetching Campflow events: {e}")
            return cached[0] if cached else []
        except Exception as e:
            logger.error(f"Unexpected error fetching Campflow events: {e}")
            return cached[0] if cached else []

    async def get_event_details(self, lst_id: str) -> Dict[str, Any] | None:
        """Helper to get a single event's metadata by list_id."""
        events = await self.get_events()
        return next((e for e in events if e.get("list_id") == lst_id), None)

    async def get_list_custom_columns(self, lst_id: str) -> List[Dict[str, Any]]:
        """Fetch custom field definitions for a specific list."""
        url = f"{self.base_url}/lists/{lst_id}/custom_columns"
        try:
            async with httpx.AsyncClient() as client:
                response = await client.get(url, headers=self._get_headers(), timeout=10.0)
                response.raise_for_status()
                return response.json().get("data", [])
        except Exception as e:
            logger.error(f"Error fetching custom columns for list {lst_id}: {e}")
            return []

    async def get_list_persons(self, lst_id: str) -> List[Dict[str, Any]]:
        """Fetch all persons/participants for a specific list."""
        url = f"{self.base_url}/lists/{lst_id}/persons"
        try:
            async with httpx.AsyncClient() as client:
                response = await client.get(url, headers=self._get_headers(), timeout=10.0)
                response.raise_for_status()
                return response.json().get("data", [])
        except Exception as e:
            logger.error(f"Error fetching persons for list {lst_id}: {e}")
            return []

    async def get_member_persons(self) -> List[Dict[str, Any]]:
        """Fetch all member persons (usually for identifying group leaders)."""
        url = f"{self.base_url}/lists/member/persons"
        try:
            async with httpx.AsyncClient() as client:
                response = await client.get(url, headers=self._get_headers(), timeout=10.0)
                response.raise_for_status()
                return response.json().get("data", [])
        except Exception as e:
            logger.error(f"Error fetching member persons: {e}")
            return []


def get_campflow_client(group_config: "GroupConfig | None" = None) -> CampflowClient:
    """Factory: returns a CampflowClient configured for the given group (or global fallback)."""
    token = _resolve_token(group_config)
    key = _cache_key(group_config)
    return CampflowClient(auth_token=token, cache_key=key)


# Global fallback client (used by notification_service and other places that
# don't have a per-group context yet)
campflow_client = get_campflow_client()
