"""Main client class for Agent Berlin SDK.

Example:
    from agentberlin import AgentBerlin

    client = AgentBerlin()  # Uses AGENTBERLIN_TOKEN env var

    # Get GA4 analytics
    analytics = client.ga4.get(project_domain="example.com")
    print(f"Traffic: {analytics.traffic.total_sessions}")

    # Page search
    result = client.pages.search(query="SEO tips")
    for page in result.similar_pages:
        print(f"  - {page.title}: {page.target_page_url}")
"""

import os
from typing import Optional

from ._http import HTTPClient
from .config import DEFAULT_BASE_URL, DEFAULT_TIMEOUT, Config, RetryConfig
from .exceptions import AgentBerlinAuthenticationError
from .resources.backlink_marketplace import BacklinkMarketplaceResource
from .resources.bing import BingResource
from .resources.brand import BrandResource
from .resources.files import FilesResource
from .resources.ga4 import GA4Resource
from .resources.google_cse import GoogleCSEResource
from .resources.gsc import GSCResource
from .resources.keywords import KeywordsResource
from .resources.llm import LLMResource
from .resources.pages import PagesResource
from .resources.reddit import RedditResource
from .resources.serpapi import SerpApiResource
from .session import load_session_config, update_session_token


class AgentBerlin:
    """Client for the Agent Berlin API.

    Args:
        token: API token. If not provided, reads from AGENTBERLIN_TOKEN env var
               or config file (~/.agentberlin/config.json).
        base_url: Base URL for the API. Defaults to https://backend.agentberlin.ai/sdk
        timeout: Request timeout in seconds. Defaults to 120.
        retry: Retry configuration. Defaults to RetryConfig() with 5 retries,
               30s base delay, 120s max delay. Pass RetryConfig(max_retries=0)
               to disable retries.
        config_path: Optional custom config file path for loading token.

    Token resolution order:
        1. Explicit token parameter
        2. AGENTBERLIN_TOKEN environment variable
        3. ~/.agentberlin/config.json
        4. .agentberlin/config.json (CWD)
        5. Custom config_path (if provided)

    Raises:
        AgentBerlinAuthenticationError: If no token is provided or found.

    Attributes:
        ga4: Google Analytics 4 resource for fetching analytics data.
        pages: Pages resource for searching and getting page details.
        keywords: Keywords resource for semantic keyword search.
        brand: Brand resource for managing brand profiles.
        google_cse: Google Custom Search resource for simple Google web searches.
        serpapi: SerpApi resource for multi-engine search (Google, Bing) with
                 various search types (web, news, images, videos, shopping).
        llm: LLM resource for AI-powered web search (Perplexity, ChatGPT, Gemini)
             and text completion (Claude, GPT, Gemini).
        files: Files resource for uploading workflow output files.
        gsc: Google Search Console resource for search analytics and URL inspection.
        reddit: Reddit resource for read-only Reddit data access.
        bing_webmaster: Bing Webmaster Tools resource for search analytics, crawl stats, and site info.
        backlink_marketplace: Backlink marketplace resource for finding guest posting and link building opportunities.
            **Warning:** Charges 2 credits per domain returned.
    """

    def __init__(
        self,
        token: Optional[str] = None,
        base_url: Optional[str] = None,
        timeout: int = DEFAULT_TIMEOUT,
        retry: Optional[RetryConfig] = None,
        config_path: Optional[str] = None,
    ) -> None:
        # Track whether token came from config (for refresh persistence)
        self._config_path = config_path
        self._token_from_config = False
        expires_at: Optional[int] = None

        # Get token with priority: explicit param > env var > config file
        self._token = token or os.environ.get("AGENTBERLIN_TOKEN")
        if not self._token:
            # Try loading from config file
            config = load_session_config(config_path)
            self._token = config.get("token")
            if self._token:
                self._token_from_config = True
                expires_at = config.get("expires_at")

        if not self._token:
            raise AgentBerlinAuthenticationError(
                "No API token provided. Set AGENTBERLIN_TOKEN environment variable, "
                "pass token parameter to AgentBerlin(), or run "
                "'agentberlin configure --token <token> --domain <domain>' to save credentials."
            )

        # Initialize config
        self._config = Config(
            base_url=base_url or DEFAULT_BASE_URL,
            timeout=timeout,
            retry=retry,
        )

        # Callback to persist refreshed token to config file
        on_token_refreshed = None
        if self._token_from_config:

            def on_token_refreshed(new_token: str, new_expires_at: int) -> None:
                update_session_token(new_token, new_expires_at, self._config_path)

        # Initialize HTTP client
        self._http = HTTPClient(
            token=self._token,
            base_url=self._config.base_url,
            timeout=self._config.timeout,
            retry_config=self._config.retry,
            expires_at=expires_at,
            on_token_refreshed=on_token_refreshed,
        )

        # Initialize resources
        self.ga4 = GA4Resource(self._http)
        self.pages = PagesResource(self._http)
        self.keywords = KeywordsResource(self._http)
        self.brand = BrandResource(self._http)
        self.google_cse = GoogleCSEResource(self._http)
        self.serpapi = SerpApiResource(self._http)
        self.llm = LLMResource(self._http)
        self.files = FilesResource(self._http)
        self.gsc = GSCResource(self._http)
        self.reddit = RedditResource(self._http)
        self.bing_webmaster = BingResource(self._http)
        self.backlink_marketplace = BacklinkMarketplaceResource(self._http)

    def __repr__(self) -> str:
        return f"AgentBerlin(base_url='{self._config.base_url}')"
