"""
Efficient API client using requests with browser session cookies
Perfect for authenticated API calls after browser_login
"""

import json
import time
from typing import Any, Dict, List, Optional
from urllib.parse import urljoin, urlparse

import requests
from mcp.types import TextContent

from ..config import ANTI_DETECTION_HEADERS, authenticated_session, logger
from .cache import get_http_cache
from .logging import log_http_request
from .metrics import get_metrics_collector, record_http_request


class SessionAPIClient:
    """Efficient API client using requests with browser cookies."""

    def __init__(
        self,
        enable_cache: bool = True,
        cache_ttl: int = 300,
        pool_connections: int = 10,
        pool_maxsize: int = 20,
        max_retries: int = 3,
        pool_block: bool = False,
    ):
        self.session = requests.Session()
        self._current_user_agent = None
        self._session_updated = False
        self._enable_cache = enable_cache
        self._cache_ttl = cache_ttl
        self._http_cache = get_http_cache() if enable_cache else None

        # Configure connection pooling
        self._pool_connections = pool_connections
        self._pool_maxsize = pool_maxsize
        self._max_retries = max_retries
        self._pool_block = pool_block

        self._setup_connection_pool()
        self._setup_headers()

    def _setup_connection_pool(self):
        """Setup connection pooling with retry strategy."""
        from requests.adapters import HTTPAdapter
        from urllib3.util.retry import Retry

        # Create retry strategy
        retry_strategy = Retry(
            total=self._max_retries,
            status_forcelist=[429, 500, 502, 503, 504],
            allowed_methods=["HEAD", "GET", "OPTIONS"],
            backoff_factor=0.3,
        )

        # Create adapter with connection pooling
        adapter = HTTPAdapter(
            max_retries=retry_strategy,
            pool_connections=self._pool_connections,
            pool_maxsize=self._pool_maxsize,
            pool_block=self._pool_block,
        )

        # Mount adapters for HTTP and HTTPS
        self.session.mount("http://", adapter)
        self.session.mount("https://", adapter)

        logger.info(
            f"🔌 Connection pool configured: {self._pool_connections} connections, "
            f"max {self._pool_maxsize} per host, {self._max_retries} retries"
        )

    def _setup_headers(self):
        """Setup headers with rotating User-Agent."""
        import random

        # Rotate User-Agent for better security
        if ANTI_DETECTION_HEADERS:
            self._current_user_agent = random.choice(ANTI_DETECTION_HEADERS)
        else:
            self._current_user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36"

        self.session.headers.update(
            {
                "User-Agent": self._current_user_agent,
                "Accept": "application/json, text/plain, */*",
                "Accept-Language": "en-US,en;q=0.9",
                "Accept-Encoding": "gzip, deflate, br",
                "Connection": "keep-alive",
                "Upgrade-Insecure-Requests": "1",
                "Sec-Fetch-Dest": "document",
                "Sec-Fetch-Mode": "navigate",
                "Sec-Fetch-Site": "none",
                "Cache-Control": "max-age=0",
            }
        )

    def update_from_browser_session(self, browser_cookies: list[dict[str, Any]] = None):
        """Update requests session with cookies from browser."""
        if browser_cookies is None and authenticated_session.get("active"):
            browser_cookies = authenticated_session.get("browser_cookies", [])

        if browser_cookies:
            for cookie_data in browser_cookies:
                try:
                    # Handle both dict and string formats
                    if isinstance(cookie_data, dict):
                        name = cookie_data.get("name", "")
                        value = cookie_data.get("value", "")
                        domain = cookie_data.get("domain", "")
                        path = cookie_data.get("path", "/")
                        secure = cookie_data.get("secure", False)
                        expires = cookie_data.get("expires")
                    elif isinstance(cookie_data, str):
                        # Simple string format: "name=value"
                        if "=" in cookie_data:
                            name, value = cookie_data.split("=", 1)
                            domain = path = ""
                            secure = False
                            expires = None
                        else:
                            continue
                    else:
                        continue

                    if name:
                        self.session.cookies.set(name, value, domain=domain, path=path)
                        if secure:
                            # Note: requests doesn't directly support secure flag in set()
                            pass

                except Exception as e:
                    logger.debug(
                        f"Failed to set cookie {name if 'name' in locals() else 'unknown'}: {e}"
                    )

            logger.info(
                f"✅ Updated API client with {len(browser_cookies)} cookies from browser session"
            )

        # Always mark as updated, even if no cookies were provided
        self._session_updated = True

    def ensure_session_updated(self):
        """Auto-update session if needed and not already updated."""
        if not hasattr(self, "_session_updated") or not self._session_updated:
            self.update_from_browser_session()
            self._session_updated = True

    def get(
        self,
        url: str,
        timeout: int = 10,
        headers: dict[str, Any] = None,
        params: dict[str, Any] = None,
        debug: bool = False,
        use_cache: bool = True,
        cache_ttl: Optional[int] = None,
    ) -> dict[str, Any]:
        """GET request with browser session cookies."""

        # Check cache first
        cache_hit = False
        if self._enable_cache and use_cache and self._http_cache:
            cached_response = self._http_cache.get_response("GET", url, params, headers)
            if cached_response:
                if debug:
                    logger.debug(f"📋 Cache hit for {url}")
                cache_hit = True
                record_http_request(
                    "GET",
                    url,
                    cached_response.get("status_code", 200),
                    0,
                    cache_hit=True,
                )  # 0 duration for cache hits
                return cached_response

        # Merge headers
        request_headers = self.session.headers.copy()
        if headers:
            request_headers.update(headers)

        try:
            logger.debug(f"🚀 API GET: {url}") if debug else None
            start_time = time.time()

            response = self.session.get(
                url,
                headers=request_headers,
                params=params,
                timeout=timeout,
                allow_redirects=True,
            )

            response_time = time.time() - start_time

            # Try to parse JSON
            content = ""
            json_data = None
            try:
                if "application/json" in response.headers.get("content-type", ""):
                    json_data = response.json()
                    content = json.dumps(json_data, indent=2, ensure_ascii=False)
                else:
                    content = response.text
            except:
                content = response.text

            result = {
                "method": "api_with_session",
                "url": url,
                "final_url": response.url,
                "status_code": response.status_code,
                "content_type": response.headers.get("content-type", ""),
                "content": content,
                "json_data": json_data,
                "size": len(content),
                "cookies_count": len(self.session.cookies),
                "authenticated": len(self.session.cookies) > 0,
                "response_time_seconds": response_time,
                "response_headers": dict(response.headers) if debug else {},
                "success": response.status_code < 400,
            }

            if debug:
                result["debug_info"] = {
                    "redirect_chain": [url, response.url] if response.url != url else [url],
                    "response_time": f"{response_time:.2f}s",
                    "cookies_used": len(self.session.cookies),
                }

            # Record metrics
            record_http_request(
                "GET",
                url,
                result.get("status_code", 0),
                response_time,
                cache_hit=cache_hit,
            )

            # Structured logging
            log_http_request("GET", url, result.get("status_code", 0), response_time, cache_hit)

            # Cache successful responses
            if (
                self._enable_cache
                and self._http_cache
                and self._http_cache.is_cacheable_response(result)
            ):
                ttl = cache_ttl if cache_ttl is not None else self._cache_ttl
                try:
                    self._http_cache.set_response("GET", url, result, params, headers, ttl)
                    if debug:
                        logger.debug(f"💾 Cached response for {url} (TTL: {ttl}s)")
                except Exception as e:
                    logger.debug(f"Failed to cache response for {url}: {e}")

            return result

        except Exception as e:
            logger.error(f"API GET error for {url}: {e}")
            # Record failed request metrics
            record_http_request("GET", url, 0, time.time() - start_time, cache_hit=False)
            # Structured logging for errors
            log_http_request("GET", url, 0, time.time() - start_time, cache_hit=False, error=str(e))
            return {
                "method": "api_with_session",
                "url": url,
                "success": False,
                "error": str(e),
                "status_code": 0,
            }

    def post(
        self,
        url: str,
        data: dict[str, Any] = None,
        json_data: dict[str, Any] = None,
        headers: dict[str, Any] = None,
        timeout: int = 10,
        debug: bool = False,
        use_cache: bool = True,
        cache_ttl: Optional[int] = None,
    ) -> dict[str, Any]:
        """POST request with browser session cookies."""
        # POST requests are typically not cached (they modify data)
        # But we can cache GET-like POST requests if needed

        # Merge headers
        request_headers = self.session.headers.copy()
        if headers:
            request_headers.update(headers)

        try:
            logger.debug(f"🚀 API POST: {url}") if debug else None
            start_time = time.time()

            # Prepare data
            post_data = None
            if json_data:
                request_headers["Content-Type"] = "application/json"
                post_data = json.dumps(json_data)
            elif data:
                post_data = data

            response = self.session.post(
                url,
                data=post_data,
                headers=request_headers,
                timeout=timeout,
                allow_redirects=True,
            )

            response_time = time.time() - start_time

            # Try to parse JSON
            content = ""
            response_json = None
            try:
                if "application/json" in response.headers.get("content-type", ""):
                    response_json = response.json()
                    content = json.dumps(response_json, indent=2, ensure_ascii=False)
                else:
                    content = response.text
            except:
                content = response.text

            result = {
                "method": "api_with_session",
                "url": url,
                "final_url": response.url,
                "status_code": response.status_code,
                "content_type": response.headers.get("content-type", ""),
                "content": content,
                "json_data": response_json,
                "size": len(content),
                "cookies_count": len(self.session.cookies),
                "authenticated": len(self.session.cookies) > 0,
                "response_time_seconds": response_time,
                "response_headers": dict(response.headers) if debug else {},
                "success": response.status_code < 400,
            }

            if debug:
                result["debug_info"] = {
                    "redirect_chain": [url, response.url] if response.url != url else [url],
                    "response_time": f"{response_time:.2f}s",
                    "cookies_used": len(self.session.cookies),
                    "data_sent": bool(data or json_data),
                }

            # Record metrics and structured logging
            record_http_request(
                "POST",
                url,
                result.get("status_code", 0),
                response_time,
                cache_hit=False,
            )
            log_http_request(
                "POST",
                url,
                result.get("status_code", 0),
                response_time,
                cache_hit=False,
            )

            return result

        except Exception as e:
            logger.error(f"API POST error for {url}: {e}")
            # Record failed request metrics and structured logging
            record_http_request("POST", url, 0, time.time() - start_time, cache_hit=False)
            log_http_request(
                "POST", url, 0, time.time() - start_time, cache_hit=False, error=str(e)
            )
            return {
                "method": "api_with_session",
                "url": url,
                "success": False,
                "error": str(e),
                "status_code": 0,
            }

    def get_cookies_info(self) -> dict[str, Any]:
        """Get current session cookies information."""
        cookies = []
        for cookie in self.session.cookies:
            cookies.append(
                {
                    "name": cookie.name,
                    "value": cookie.value,
                    "domain": cookie.domain,
                    "path": cookie.path,
                    "secure": cookie.secure,
                    "expires": cookie.expires,
                }
            )

        return {
            "cookies_count": len(cookies),
            "cookies": cookies,
            "has_session": len(cookies) > 0,
        }

    def get_current_user_agent(self) -> str:
        """Get current User-Agent."""
        return self._current_user_agent

    def rotate_user_agent(self):
        """Rotate to a new User-Agent."""
        import random

        if ANTI_DETECTION_HEADERS:
            old_ua = self._current_user_agent
            self._current_user_agent = random.choice(ANTI_DETECTION_HEADERS)
            self.session.headers.update({"User-Agent": self._current_user_agent})
            logger.info(
                f"🔄 Rotated User-Agent: {old_ua[:50]}... → {self._current_user_agent[:50]}..."
            )

    def clear_cookies(self):
        """Clear all cookies from session."""
        self.session.cookies.clear()
        self._session_updated = False  # Reset session update flag
        logger.info("🗑️ API client cookies cleared")

    def get_performance_info(self) -> dict[str, Any]:
        """Get current performance and connection information."""
        cache_info = {}
        if self._http_cache:
            cache_stats = self._http_cache.cache.get_stats()
            cache_info = {
                "cache_enabled": True,
                "cache_size": cache_stats.get("total_items", 0),
                "cache_max_size": cache_stats.get("max_size", 0),
                "cache_ttl": self._cache_ttl,
                "cache_hit_rate": 0.0,  # Would need hit/miss counters
            }
        else:
            cache_info = {"cache_enabled": False}

        pool_info = self.get_connection_pool_stats()

        # Get metrics summary
        metrics_collector = get_metrics_collector()
        metrics_summary = metrics_collector.get_summary()

        return {
            "user_agent": self._current_user_agent,
            "cookies_count": len(self.session.cookies),
            "session_updated": self._session_updated,
            "headers_count": len(self.session.headers),
            "has_browser_session": authenticated_session.get("active", False),
            **cache_info,
            **pool_info,
            "metrics": {
                "http_requests_total": metrics_summary.get("counters", {}).get(
                    "http_requests_total", 0
                ),
                "http_cache_hits": metrics_summary.get("counters", {}).get("http_cache_hits", 0),
                "http_cache_misses": metrics_summary.get("counters", {}).get(
                    "http_cache_misses", 0
                ),
                "connection_pool_active": metrics_summary.get("gauges", {}).get(
                    "connection_pool_active", 0
                ),
                "uptime_seconds": metrics_summary.get("uptime_seconds", 0),
            },
        }

    def clear_cache(self) -> None:
        """Clear HTTP cache."""
        if self._http_cache:
            self._http_cache.cache.clear()
            logger.info("🗑️ HTTP cache cleared")

    def get_cache_stats(self) -> dict[str, Any]:
        """Get HTTP cache statistics."""
        if self._http_cache:
            return self._http_cache.cache.get_stats()
        return {"cache_enabled": False}

    def cleanup_cache(self) -> int:
        """Clean up expired cache entries."""
        if self._http_cache:
            return self._http_cache.cache.cleanup_expired()
        return 0

    def get_connection_pool_stats(self) -> dict[str, Any]:
        """Get connection pool statistics."""
        try:
            # Get adapter for HTTPS (similar for HTTP)
            https_adapter = self.session.adapters.get("https://")
            if https_adapter and hasattr(https_adapter, "poolmanager"):
                pool_manager = https_adapter.poolmanager
                stats = {
                    "pool_connections": self._pool_connections,
                    "pool_maxsize": self._pool_maxsize,
                    "max_retries": self._max_retries,
                    "pool_block": self._pool_block,
                    "active_connections": len(pool_manager.pools)
                    if hasattr(pool_manager, "pools")
                    else 0,
                    "total_pools": len(pool_manager.pools) if hasattr(pool_manager, "pools") else 0,
                }
                return stats
        except Exception as e:
            logger.debug(f"Could not get connection pool stats: {e}")

        return {
            "pool_connections": self._pool_connections,
            "pool_maxsize": self._pool_maxsize,
            "max_retries": self._max_retries,
            "pool_block": self._pool_block,
            "stats_available": False,
        }


# Global API client instance
api_client = SessionAPIClient()


def get_api_client() -> SessionAPIClient:
    """Get global API client instance."""
    return api_client
