"""Google Keyword Planner API 封装.

提供 Google Ads API 的关键词研究功能，
支持异步调用、结果缓存和限流控制。
"""

import asyncio
import json
from dataclasses import asdict, dataclass
from datetime import datetime, timedelta
from pathlib import Path
from typing import Any

import aiohttp

from src.utils.rate_limiter import TokenBucketRateLimiter


@dataclass
class KeywordData:
    """关键词数据类.

    Attributes:
        keyword: 关键词
        avg_monthly_searches: 平均月搜索量
        competition: 竞争度 (LOW, MEDIUM, HIGH)
        low_cpc: 最低 CPC
        high_cpc: 最高 CPC
        trend: 12个月搜索趋势列表
        fetched_at: 数据获取时间
    """

    keyword: str
    avg_monthly_searches: int
    competition: str
    low_cpc: float
    high_cpc: float
    trend: list[int]
    fetched_at: datetime

    def to_dict(self) -> dict[str, Any]:
        """转换为字典."""
        data = asdict(self)
        data["fetched_at"] = self.fetched_at.isoformat()
        return data


class GoogleKeywordPlanner:
    """Google Keyword Planner API 封装.

    提供关键词数据获取、缓存和限流功能。
    支持异步上下文管理器。

    Example:
        >>> async with GoogleKeywordPlanner("api_key") as planner:
        ...     data = await planner.get_keyword_data("seo tools")
    """

    def __init__(
        self,
        api_key: str,
        cache_dir: str = ".cache",
        cache_ttl_hours: int = 24,
    ):
        """初始化.

        Args:
            api_key: Google Ads API 密钥
            cache_dir: 缓存目录
            cache_ttl_hours: 缓存有效期（小时）
        """
        self.api_key = api_key
        self.cache_dir = Path(cache_dir)
        self.cache_dir.mkdir(exist_ok=True)
        self.cache_ttl = timedelta(hours=cache_ttl_hours)
        self.rate_limiter = TokenBucketRateLimiter()
        self.session: aiohttp.ClientSession | None = None

    async def __aenter__(self) -> "GoogleKeywordPlanner":
        """异步上下文入口."""
        self.session = aiohttp.ClientSession()
        return self

    async def __aexit__(
        self,
        exc_type: type | None,
        exc_val: BaseException | None,
        exc_tb: Any | None,
    ) -> None:
        """异步上下文出口."""
        if self.session:
            await self.session.close()

    def _get_cache_path(self, keyword: str) -> Path:
        """获取缓存文件路径."""
        safe_keyword = "".join(c if c.isalnum() else "_" for c in keyword)
        return self.cache_dir / f"kw_{safe_keyword}.json"

    def _is_cache_valid(self, cache_path: Path) -> bool:
        """检查缓存是否有效."""
        if not cache_path.exists():
            return False
        mtime = datetime.fromtimestamp(cache_path.stat().st_mtime)
        return datetime.now() - mtime < self.cache_ttl

    async def _fetch_from_api(self, keyword: str) -> KeywordData:
        """从 API 获取数据."""
        async with self.rate_limiter:
            # TODO: 实现真实 API 调用
            # 当前使用模拟数据
            await asyncio.sleep(0.1)  # 模拟 API 延迟
            return KeywordData(
                keyword=keyword,
                avg_monthly_searches=1000,
                competition="MEDIUM",
                low_cpc=0.5,
                high_cpc=2.0,
                trend=[800, 900, 1000, 1100, 1000, 900, 1000, 1100, 1200, 1100, 1000, 1000],
                fetched_at=datetime.now(),
            )

    async def get_keyword_data(self, keyword: str) -> KeywordData:
        """获取关键词数据.

        优先从缓存获取，缓存无效则从 API 获取。

        Args:
            keyword: 关键词

        Returns:
            KeywordData 对象
        """
        cache_path = self._get_cache_path(keyword)

        # 检查缓存
        if self._is_cache_valid(cache_path):
            with open(cache_path, encoding="utf-8") as f:
                data = json.load(f)
                data["fetched_at"] = datetime.fromisoformat(data["fetched_at"])
                return KeywordData(**data)

        # 从 API 获取
        result = await self._fetch_from_api(keyword)

        # 保存缓存
        with open(cache_path, "w", encoding="utf-8") as f:
            json.dump(result.to_dict(), f, indent=2)

        return result
