"""Configuration management for open-webview-e2e CLI."""

from __future__ import annotations

import json
import os
from dataclasses import dataclass, asdict
from pathlib import Path
from typing import Optional


@dataclass
class CLIConfig:
    """CLI configuration schema."""

    cdp_endpoint: Optional[str] = None
    webdriver_endpoint: Optional[str] = None
    driver: str = "auto"
    browser: str = "chromium"
    timeout_action: int = 30000
    timeout_navigation: int = 60000
    output_dir: str = "./screenshots"
    console_level: str = "info"
    snapshot_format: str = "yaml"
    auto_snapshot: bool = True
    test_id_attribute: str = "data-testid"
    reference_prefix: str = "e"
    max_snapshot_elements: int = 50

    def to_dict(self) -> dict:
        """Convert to dictionary."""
        return asdict(self)

    @classmethod
    def from_dict(cls, data: dict) -> CLIConfig:
        """Create from dictionary."""
        return cls(**{k: v for k, v in data.items() if k in cls.__annotations__})


class ConfigLoader:
    """Configuration loader with multiple sources support."""

    DEFAULT_CONFIG_FILES = [
        ".webview-cli.json",
        ".webview-cli.yaml",
        "webview-cli.json",
        "webview-cli.yaml",
    ]

    ENV_PREFIX = "WEBVIEW_"

    def __init__(self):
        self.config = CLIConfig()

    def load(self, config_path: Optional[str] = None) -> CLIConfig:
        """Load configuration from all sources.

        Priority: CLI args > Environment variables > Config file > Defaults
        """
        self.config = CLIConfig()

        config_file = self._find_config_file(config_path)
        if config_file:
            self._load_from_file(config_file)

        self._load_from_env()

        return self.config

    def _find_config_file(self, config_path: Optional[str]) -> Optional[Path]:
        """Find configuration file."""
        if config_path:
            path = Path(config_path)
            if path.exists():
                return path

        for filename in self.DEFAULT_CONFIG_FILES:
            path = Path.cwd() / filename
            if path.exists():
                return path

        return None

    def _load_from_file(self, path: Path) -> None:
        """Load configuration from file."""
        try:
            with open(path, "r", encoding="utf-8") as f:
                if path.suffix == ".json":
                    data = json.load(f)
                else:
                    import yaml
                    data = yaml.safe_load(f)

            loaded = CLIConfig.from_dict(data)
            for key, value in loaded.to_dict().items():
                if value is not None:
                    setattr(self.config, key, value)
        except Exception as e:
            print(f"Warning: Failed to load config from {path}: {e}")

    def _load_from_env(self) -> None:
        """Load configuration from environment variables."""
        env_mappings = {
            "WEBVIEW_CDP_ENDPOINT": "cdp_endpoint",
            "WEBVIEW_WEBDRIVER_ENDPOINT": "webdriver_endpoint",
            "WEBVIEW_DRIVER": "driver",
            "WEBVIEW_BROWSER": "browser",
            "WEBVIEW_TIMEOUT_ACTION": "timeout_action",
            "WEBVIEW_TIMEOUT_NAVIGATION": "timeout_navigation",
            "WEBVIEW_OUTPUT_DIR": "output_dir",
            "WEBVIEW_CONSOLE_LEVEL": "console_level",
            "WEBVIEW_SNAPSHOT_FORMAT": "snapshot_format",
            "WEBVIEW_AUTO_SNAPSHOT": "auto_snapshot",
            "WEBVIEW_TEST_ID_ATTRIBUTE": "test_id_attribute",
            "WEBVIEW_REFERENCE_PREFIX": "reference_prefix",
            "WEBVIEW_MAX_SNAPSHOT_ELEMENTS": "max_snapshot_elements",
        }

        for env_key, config_key in env_mappings.items():
            value = os.environ.get(env_key)
            if value is not None:
                if config_key in ("timeout_action", "timeout_navigation", "max_snapshot_elements"):
                    value = int(value)
                elif config_key == "auto_snapshot":
                    value = value.lower() in ("true", "1", "yes")
                setattr(self.config, config_key, value)

    def save(self, path: str) -> None:
        """Save configuration to file."""
        path = Path(path)
        with open(path, "w", encoding="utf-8") as f:
            if path.suffix == ".json":
                json.dump(self.config.to_dict(), f, indent=2)
            else:
                import yaml
                yaml.dump(self.config.to_dict(), f, default_flow_style=False)


_config_loader: Optional[ConfigLoader] = None


def get_config_loader() -> ConfigLoader:
    """Get global config loader instance."""
    global _config_loader
    if _config_loader is None:
        _config_loader = ConfigLoader()
    return _config_loader


def load_config(config_path: Optional[str] = None) -> CLIConfig:
    """Load configuration from all sources."""
    loader = get_config_loader()
    return loader.load(config_path)
