"""
Lightweight config classes for building crawl requests.

These are simplified versions of crawl4ai's BrowserConfig and CrawlerRunConfig.
They only handle serialization for the Docker API — no browser or crawling logic.
"""

from enum import Enum
from typing import Any, Dict, List, Optional


class CacheMode(Enum):
    """Cache mode for crawl requests."""
    ENABLED = "enabled"
    DISABLED = "disabled"
    BYPASS = "bypass"
    WRITE_ONLY = "write_only"
    READ_ONLY = "read_only"


class _SerializableConfig:
    """Base class with dict serialization for the Docker API."""

    def dump(self) -> Dict[str, Any]:
        """Serialize to the format expected by the crawl4ai Docker API."""
        params = {}
        for key, value in self.__dict__.items():
            if key.startswith("_"):
                continue
            if value is None:
                continue
            if isinstance(value, _SerializableConfig):
                params[key] = value.dump()
            elif isinstance(value, Enum):
                params[key] = {"type": type(value).__name__, "params": value.value}
            elif isinstance(value, dict):
                params[key] = {"type": "dict", "value": value}
            elif isinstance(value, list):
                params[key] = value
            else:
                params[key] = value
        return {"type": type(self).__name__, "params": params}


class BrowserConfig(_SerializableConfig):
    """Browser configuration for crawl requests.

    Only includes fields relevant to the Docker API.
    For the full set of options, see the crawl4ai documentation.
    """

    def __init__(
        self,
        headless: bool = True,
        browser_type: str = "chromium",
        viewport_width: int = 1080,
        viewport_height: int = 720,
        user_agent: Optional[str] = None,
        proxy: Optional[str] = None,
        headers: Optional[Dict[str, str]] = None,
        text_mode: bool = False,
        java_script_enabled: bool = True,
        ignore_https_errors: bool = True,
        accept_downloads: bool = False,
        **kwargs: Any,
    ):
        self.headless = headless
        self.browser_type = browser_type
        self.viewport_width = viewport_width
        self.viewport_height = viewport_height
        self.user_agent = user_agent
        self.proxy = proxy
        self.headers = headers
        self.text_mode = text_mode
        self.java_script_enabled = java_script_enabled
        self.ignore_https_errors = ignore_https_errors
        self.accept_downloads = accept_downloads
        # Pass through any extra kwargs for forward compatibility
        for k, v in kwargs.items():
            setattr(self, k, v)


class CrawlerRunConfig(_SerializableConfig):
    """Crawler run configuration for crawl requests.

    Only includes fields relevant to the Docker API.
    For the full set of options, see the crawl4ai documentation.
    """

    def __init__(
        self,
        cache_mode: Optional[CacheMode] = None,
        css_selector: Optional[str] = None,
        word_count_threshold: int = 200,
        verbose: bool = True,
        stream: bool = False,
        excluded_tags: Optional[List[str]] = None,
        exclude_external_links: bool = False,
        exclude_social_media_links: bool = False,
        screenshot: bool = False,
        pdf: bool = False,
        scan_full_page: bool = False,
        remove_overlay_elements: bool = False,
        wait_for: Optional[str] = None,
        delay_before_return_html: float = 0.1,
        js_code: Optional[List[str]] = None,
        **kwargs: Any,
    ):
        self.cache_mode = cache_mode
        self.css_selector = css_selector
        self.word_count_threshold = word_count_threshold
        self.verbose = verbose
        self.stream = stream
        self.excluded_tags = excluded_tags
        self.exclude_external_links = exclude_external_links
        self.exclude_social_media_links = exclude_social_media_links
        self.screenshot = screenshot
        self.pdf = pdf
        self.scan_full_page = scan_full_page
        self.remove_overlay_elements = remove_overlay_elements
        self.wait_for = wait_for
        self.delay_before_return_html = delay_before_return_html
        self.js_code = js_code
        # Pass through any extra kwargs for forward compatibility
        for k, v in kwargs.items():
            setattr(self, k, v)
