"""
SITAR API Base Service

Base service class for SITAR API authentication and HTTP requests.
All specific resource services inherit from this.
"""

import os
from typing import Optional, Dict, Any, List, Tuple
from datetime import datetime, timedelta
import httpx


class SitarAPIBaseService:
    """Base service for SITAR API integration with authentication"""

    _token: Optional[str] = None
    _token_expires: Optional[datetime] = None

    @staticmethod
    def _parse_paginated_list_and_total(data: Any) -> Tuple[List[Any], int]:
        """
        Paginated list endpoints (fracciones, fracciones-usa) return:
        { "data": [...], "total", "page", "limit", "total_pages" }.
        Older responses may be a plain JSON array; then total is len(rows) for that page only.
        """
        if isinstance(data, list):
            return data, len(data)
        if isinstance(data, dict) and isinstance(data.get("data"), list):
            rows = data["data"]
            raw_total = data.get("total")
            total = int(raw_total) if raw_total is not None else len(rows)
            return rows, total
        raise ValueError(
            f"Unexpected SITAR list response shape: {type(data).__name__}"
        )

    @staticmethod
    def _unwrap_paginated_list(data: Any) -> List[Any]:
        rows, _ = SitarAPIBaseService._parse_paginated_list_and_total(data)
        return rows

    def __init__(self):
        """Initialize base service with API credentials"""
        self.base_url = os.getenv("SITAR_API_URL")
        self.username = os.getenv("SITAR_API_USER")
        self.password = os.getenv("SITAR_API_PASSWORD")
        self.timeout = 30.0

        if not all([self.base_url, self.username, self.password]):
            raise ValueError(
                "Missing SITAR API configuration. "
                "Set SITAR_API_URL, SITAR_API_USER, and SITAR_API_PASSWORD environment variables."
            )

    async def _get_token(self) -> str:
        """
        Get authentication token, refreshing if necessary

        Returns:
            str: Bearer token for API authentication

        Raises:
            httpx.HTTPError: If authentication fails
        """
        # Return cached token if still valid
        if self._token and self._token_expires and datetime.now() < self._token_expires:
            return self._token

        # Authenticate and get new token
        login_url = f"{self.base_url}/fractions/api/v1/auth/login"
        payload = {"username": self.username, "password": self.password}

        async with httpx.AsyncClient(timeout=self.timeout) as client:
            response = await client.post(login_url, json=payload)
            response.raise_for_status()

            data = response.json()
            self._token = data.get("access_token") or data.get("token")

            if not self._token:
                raise ValueError("No token received from SITAR API")

            # Set token expiration (assume 1 hour if not specified)
            self._token_expires = datetime.now() + timedelta(hours=1)

            return self._token

    async def _make_request(
        self,
        method: str,
        endpoint: str,
        params: Optional[Dict[str, Any]] = None,
        json_data: Optional[Dict[str, Any]] = None,
    ) -> Any:
        """
        Make authenticated request to SITAR API

        Args:
            method: HTTP method (GET, POST, etc.)
            endpoint: API endpoint path
            params: Query parameters
            json_data: JSON body data

        Returns:
            JSON response data

        Raises:
            httpx.HTTPError: If request fails
        """
        token = await self._get_token()
        # Ensure no double slash between fractures and endpoint
        endpoint = endpoint.lstrip("/")
        url = f"{self.base_url}/fractions/{endpoint}"
        headers = {
            "Authorization": f"Bearer {token}",
            "Content-Type": "application/json",
        }

        async with httpx.AsyncClient(timeout=self.timeout) as client:
            response = await client.request(
                method=method,
                url=url,
                params=params,
                json=json_data,
                headers=headers,
            )
            response.raise_for_status()
            
            # DEBUG LOGGING for SITAR inspection
            if "fracciones" in url:
                import logging
                logger = logging.getLogger(__name__)                
                try:
                    data = response.json()                    
                    return data
                except Exception:
                    logger.error(f"Error parsing SITAR API Response Body: {response.text}")
                    pass

            return response.json()

    def _get_token_sync(self) -> str:
        """Same token cache as async path; safe for sync validators (no running asyncio loop)."""
        if self._token and self._token_expires and datetime.now() < self._token_expires:
            return self._token

        login_url = f"{self.base_url}/fractions/api/v1/auth/login"
        payload = {"username": self.username, "password": self.password}

        with httpx.Client(timeout=self.timeout) as client:
            response = client.post(login_url, json=payload)
            response.raise_for_status()
            data = response.json()
            token = data.get("access_token") or data.get("token")
            if not token:
                raise ValueError("No token received from SITAR API")
            self._token = token
            self._token_expires = datetime.now() + timedelta(hours=1)
            return token

    def _make_request_sync(
        self,
        method: str,
        endpoint: str,
        params: Optional[Dict[str, Any]] = None,
        json_data: Optional[Dict[str, Any]] = None,
    ) -> Any:
        token = self._get_token_sync()
        endpoint = endpoint.lstrip("/")
        url = f"{self.base_url}/fractions/{endpoint}"
        headers = {
            "Authorization": f"Bearer {token}",
            "Content-Type": "application/json",
        }
        with httpx.Client(timeout=self.timeout) as client:
            response = client.request(
                method=method,
                url=url,
                params=params,
                json=json_data,
                headers=headers,
            )
            response.raise_for_status()
            return response.json()
