import logging
from typing import Any, Dict, List

import aiohttp

from app.core.config import settings

logger = logging.getLogger(__name__)


class FedExApiClient:
    def __init__(self) -> None:
        self.base_url = (settings.FEDEX_BASE_URL or "").rstrip("/")
        self.timeout_seconds = max(5, int(settings.FEDEX_TIMEOUT_SECONDS or 20))

    def _headers(self) -> Dict[str, str]:
        return {
            "Content-Type": "application/json",
            "X-API-KEY": settings.FEDEX_API_KEY or "",
            "X-API-SECRET": settings.FEDEX_API_SECRET or "",
            "X-FEDEX-ACCOUNT": settings.FEDEX_ACCOUNT_NUMBER or "",
        }

    async def create_shipment(self, payload: Dict[str, Any]) -> Dict[str, Any]:
        if not self.base_url:
            raise RuntimeError("FedEx base URL is not configured")

        url = f"{self.base_url}/shipments"
        logger.info("🚀 FedEx create shipment request sent")

        timeout = aiohttp.ClientTimeout(total=self.timeout_seconds)
        async with aiohttp.ClientSession(timeout=timeout) as session:
            async with session.post(url, json=payload, headers=self._headers()) as response:
                body = await response.text()
                if response.status >= 400:
                    logger.error("❌ FedEx create shipment failed (%s): %s", response.status, body)
                    raise RuntimeError(f"FedEx create shipment failed: HTTP {response.status}")
                return await response.json()

    async def get_tracking(self, tracking_number: str) -> Dict[str, Any]:
        if not self.base_url:
            raise RuntimeError("FedEx base URL is not configured")

        url = f"{self.base_url}/tracking/{tracking_number}"
        timeout = aiohttp.ClientTimeout(total=self.timeout_seconds)
        async with aiohttp.ClientSession(timeout=timeout) as session:
            async with session.get(url, headers=self._headers()) as response:
                body = await response.text()
                if response.status >= 400:
                    logger.error("❌ FedEx tracking failed (%s): %s", response.status, body)
                    raise RuntimeError(f"FedEx tracking failed: HTTP {response.status}")
                return await response.json()

    async def cancel_shipment(self, tracking_number: str) -> Dict[str, Any]:
        if not self.base_url:
            raise RuntimeError("FedEx base URL is not configured")

        url = f"{self.base_url}/shipments/{tracking_number}/cancel"
        timeout = aiohttp.ClientTimeout(total=self.timeout_seconds)
        async with aiohttp.ClientSession(timeout=timeout) as session:
            async with session.post(url, headers=self._headers()) as response:
                body = await response.text()
                if response.status >= 400:
                    logger.error("❌ FedEx cancel failed (%s): %s", response.status, body)
                    raise RuntimeError(f"FedEx cancel failed: HTTP {response.status}")
                return await response.json()


def parse_tracking_events(payload: Dict[str, Any]) -> List[Dict[str, Any]]:
    raw_events = payload.get("events") or []
    if not isinstance(raw_events, list):
        return []

    normalized: List[Dict[str, Any]] = []
    for event in raw_events:
        if not isinstance(event, dict):
            continue
        normalized.append(
            {
                "status": str(event.get("status") or "unknown"),
                "description": event.get("description"),
                "event_timestamp": event.get("event_timestamp") or event.get("timestamp"),
                "location_city": event.get("location_city") or event.get("city"),
                "location_country": event.get("location_country") or event.get("country"),
            }
        )
    return normalized
