"""配置管理模块.

使用 Pydantic v2 Settings 管理应用配置，
支持 YAML 配置文件和环境变量覆盖。
"""

import os
from pathlib import Path
from typing import Any

import yaml  # type: ignore[import-untyped]
from pydantic import Field
from pydantic_settings import BaseSettings, SettingsConfigDict  # type: ignore[import-untyped]


class Settings(BaseSettings):
    """应用配置类.

    支持从 config/settings.yaml 和 .env 文件加载配置。
    环境变量优先级高于配置文件。

    Attributes:
        google_ads_api_key: Google Ads API 密钥
        gsc_credentials_path: Google Search Console 凭证路径
        rate_limit_requests: 限流请求数（默认 100）
        rate_limit_window: 限流时间窗口秒数（默认 60）
        cache_ttl_hours: 缓存 TTL 小时数（默认 24）
        cache_dir: 缓存目录（默认 .cache）
        log_level: 日志级别（默认 INFO）
        log_file: 日志文件路径（可选）
    """

    model_config = SettingsConfigDict(
        env_file=".env",
        env_file_encoding="utf-8",
        extra="ignore",
        case_sensitive=False,
    )

    # API Keys
    google_ads_api_key: str | None = Field(default=None, description="Google Ads API 密钥")
    gsc_credentials_path: str | None = Field(
        default=None, description="Google Search Console 凭证路径"
    )

    # 限流设置
    rate_limit_requests: int = Field(default=100, ge=1, description="限流请求数")
    rate_limit_window: int = Field(default=60, ge=1, description="限流时间窗口秒数")

    # 缓存设置
    cache_ttl_hours: int = Field(default=24, ge=1, description="缓存 TTL 小时数")
    cache_dir: str = Field(default=".cache", description="缓存目录")

    # 日志设置
    log_level: str = Field(default="INFO", pattern=r"^(DEBUG|INFO|WARNING|ERROR|CRITICAL)$")
    log_file: str | None = Field(default=None, description="日志文件路径")

    # 数据库设置
    database_url: str = Field(default="sqlite:///data/geo_seo.db", description="数据库 URL")

    @classmethod
    def from_yaml(cls, path: str) -> "Settings":
        """从 YAML 文件加载配置.

        Args:
            path: YAML 配置文件路径

        Returns:
            Settings 实例

        Raises:
            FileNotFoundError: 配置文件不存在
            yaml.YAMLError: YAML 解析错误
        """
        path_obj = Path(path)
        if not path_obj.exists():
            raise FileNotFoundError(f"配置文件不存在: {path}")

        with open(path_obj, encoding="utf-8") as f:
            config = yaml.safe_load(f)

        if not isinstance(config, dict):
            raise ValueError("配置文件必须是 YAML 对象")

        # 展平嵌套配置
        flattened = _flatten_config(config)
        return cls(**flattened)


def _flatten_config(config: dict[str, Any], prefix: str = "") -> dict[str, Any]:
    """展平嵌套配置字典.

    Args:
        config: 嵌套配置字典
        prefix: 键前缀

    Returns:
        展平后的字典
    """
    result: dict[str, Any] = {}
    for key, value in config.items():
        new_key = f"{prefix}{key}" if not prefix else f"{prefix}_{key}"
        if isinstance(value, dict):
            result.update(_flatten_config(value, new_key))
        else:
            result[new_key] = value
    return result


def load_settings(config_path: str | None = None) -> Settings:
    """加载应用配置.

    加载优先级（从高到低）：
    1. 环境变量
    2. .env 文件
    3. config/settings.yaml
    4. 默认值

    Args:
        config_path: 配置文件路径（可选）

    Returns:
        Settings 实例
    """
    # 默认配置文件路径
    if config_path is None:
        config_path = os.environ.get("GEO_SEO_CONFIG", "config/settings.yaml")

    path_obj = Path(config_path)

    # 如果配置文件存在，从 YAML 加载
    if path_obj.exists():
        return Settings.from_yaml(str(path_obj))

    # 否则使用默认设置（从环境变量/.env 加载）
    return Settings()
