"""Cloudflare 适配器（REST API v4，Bearer Token）

API 文档：https://developers.cloudflare.com/api/
所需配置：{"api_token": "..."}（建议用 API Token，权限含 Zone:Read / Account:Read / Registrar:Read）
Cloudflare 无传统 VPS，主要同步托管域名（zones）；Workers/R2/Tunnel 子资产留待后续阶段。
域名到期日通过 Registrar API（/accounts/{id}/registrar/domains）补充获取。
"""

import httpx

from app.adapters.base import BaseAdapter, NormalizedDomain
from app.adapters.registry import register


@register("cloudflare-api")
class CloudflareAdapter(BaseAdapter):
    required_config = ["api_token"]
    BASE = "https://api.cloudflare.com/client/v4"

    def _headers(self) -> dict:
        return {"Authorization": f"Bearer {self.config.get('api_token', '')}"}

    def _get(self, path: str) -> dict:
        with httpx.Client(timeout=30) as client:
            resp = client.get(self.BASE + path, headers=self._headers())
            resp.raise_for_status()
            data = resp.json()
            if not data.get("success", True):
                errors = data.get("errors", [])
                raise RuntimeError(errors[0].get("message") if errors else "Cloudflare API 返回失败")
            return data

    def test_connection(self) -> dict:
        try:
            data = self._get("/user/tokens/verify")
            status = data.get("result", {}).get("status")
            if status == "active":
                return {"ok": True, "message": "API Token 有效"}
            return {"ok": False, "message": f"Token 状态异常：{status}"}
        except httpx.HTTPStatusError as e:
            return {"ok": False, "message": f"HTTP {e.response.status_code}：Token 无效或权限不足"}
        except Exception as e:  # noqa: BLE001
            return {"ok": False, "message": str(e)}

    def list_domains(self) -> list:
        # 先拉取 Registrar 域名到期日映射（domain_name -> expires_at ISO 日期）
        expiry_map = self._registrar_expiry_map()

        result = []
        page = 1
        while True:
            data = self._get(f"/zones?per_page=50&page={page}")
            for z in data.get("result", []):
                name = z.get("name")
                result.append(
                    NormalizedDomain(
                        external_id=z.get("id"),
                        domain_name=name,
                        registrar="cloudflare",
                        expiry_date=expiry_map.get(name),
                        status="active" if z.get("status") == "active" else (z.get("status") or "unknown"),
                        raw=z,
                    )
                )
            info = data.get("result_info", {})
            if page >= info.get("total_pages", 1):
                break
            page += 1
        return result

    def _registrar_expiry_map(self) -> dict:
        """拉取 Cloudflare Registrar 域名到期日映射 {domain_name: YYYY-MM-DD}

        流程：/accounts → 对每个 account 调 /accounts/{id}/registrar/domains。
        若 Token 无 Registrar 权限或账号无 Registrar 域名，静默返回空映射。
        """
        expiry = {}
        try:
            accounts = self._get("/accounts?per_page=50").get("result", [])
        except Exception:  # noqa: BLE001
            return expiry
        for acc in accounts:
            acc_id = acc.get("id")
            if not acc_id:
                continue
            try:
                domains = self._get(f"/accounts/{acc_id}/registrar/domains").get("result", [])
            except Exception:  # noqa: BLE001
                continue
            for d in domains:
                # Registrar API 返回的 id 是域名本身（如 example.com）
                name = d.get("id") or d.get("domain_name") or ""
                expires_at = d.get("expires_at")
                if name and expires_at:
                    # expires_at 为 ISO8601 时间戳，截取日期部分
                    expiry[name] = expires_at[:10]
        return expiry
