from __future__ import annotations
from dataclasses import dataclass
from typing import Any, Protocol
import httpx
from src.config import get_settings


class RegistrarProvider(Protocol):
    provider_id: str
    async def check_availability(self, domain: str) -> dict[str, Any]: ...
    async def register_domain(self, request: dict[str, Any], idempotency_key: str) -> dict[str, Any]: ...
    async def initiate_transfer(self, request: dict[str, Any], idempotency_key: str) -> dict[str, Any]: ...
    async def get_registration(self, domain: str) -> dict[str, Any]: ...
    async def get_registration_status(self, domain: str) -> dict[str, Any]: ...
    async def set_auto_renew(self, domain: str, enabled: bool) -> dict[str, Any]: ...
    async def search(self, query: str, limit: int = 10) -> dict[str, Any]: ...


class DNSProvider(Protocol):
    provider_id: str
    async def create_zone(self, domain: str) -> dict[str, Any]: ...
    async def create_record(self, zone_id: str, record: dict[str, Any]) -> dict[str, Any]: ...


@dataclass
class CloudflareRegistrarProvider:
    """Cloudflare Registrar adapter. Billable methods require an explicit feature flag."""
    provider_id: str = "cloudflare_registrar"

    def _settings(self):
        return get_settings()

    def _account_id(self) -> str:
        settings = self._settings()
        return settings.cloudflare_registrar_account_id or settings.cloudflare_account_id

    def _api_token(self) -> str:
        settings = self._settings()
        return settings.cloudflare_registrar_api_token or settings.cloudflare_api_token

    def _base(self) -> str:
        return f"https://api.cloudflare.com/client/v4/accounts/{self._account_id()}/registrar"

    def _headers(self) -> dict[str, str]:
        return {"Authorization": f"Bearer {self._api_token()}", "Content-Type": "application/json"}

    async def check_availability(self, domain: str) -> dict[str, Any]:
        async with httpx.AsyncClient() as client:
            r = await client.post(f"{self._base()}/domain-check", headers=self._headers(), json={"domains": [domain]})
            r.raise_for_status()
            return r.json().get("result", {})

    async def search(self, query: str, limit: int = 10) -> dict[str, Any]:
        async with httpx.AsyncClient() as client:
            r = await client.get(f"{self._base()}/domain-search", headers=self._headers(), params={"q": query, "limit": limit})
            r.raise_for_status()
            return r.json().get("result", {})

    async def register_domain(self, request: dict[str, Any], idempotency_key: str) -> dict[str, Any]:
        if not get_settings().domain_registrar_transactions_enabled:
            raise RuntimeError("Domain registration is not enabled for this environment")
        async with httpx.AsyncClient() as client:
            r = await client.post(f"{self._base()}/registrations", headers=self._headers(), json=request)
            r.raise_for_status()
            return r.json().get("result", {})

    async def initiate_transfer(self, request: dict[str, Any], idempotency_key: str) -> dict[str, Any]:
        if not get_settings().domain_registrar_transactions_enabled:
            raise RuntimeError("Domain transfers are not enabled for this environment")
        domain = request["domain_name"]
        async with httpx.AsyncClient() as client:
            r = await client.post(f"{self._base()}/registrations/{domain}/transfer-in", headers=self._headers(), json=request)
            r.raise_for_status()
            return r.json().get("result", {})

    async def get_registration(self, domain: str) -> dict[str, Any]:
        async with httpx.AsyncClient() as client:
            r = await client.get(f"{self._base()}/registrations/{domain}", headers=self._headers())
            r.raise_for_status()
            return r.json().get("result", {})

    async def get_registration_status(self, domain: str) -> dict[str, Any]:
        async with httpx.AsyncClient() as client:
            r = await client.get(f"{self._base()}/registrations/{domain}/registration-status", headers=self._headers())
            r.raise_for_status()
            return r.json().get("result", {})

    async def set_auto_renew(self, domain: str, enabled: bool) -> dict[str, Any]:
        if not get_settings().domain_registrar_transactions_enabled:
            raise RuntimeError("Registrar lifecycle changes are not enabled for this environment")
        async with httpx.AsyncClient() as client:
            r = await client.patch(f"{self._base()}/registrations/{domain}", headers=self._headers(), json={"auto_renew": enabled})
            r.raise_for_status()
            return r.json().get("result", {})


@dataclass
class CloudflareDNSProvider:
    provider_id: str = "cloudflare_dns"

    async def create_zone(self, domain: str) -> dict[str, Any]:
        from src.integrations.cloudflare_client import CloudflareClient
        return await CloudflareClient().create_zone(domain)

    async def create_record(self, zone_id: str, record: dict[str, Any]) -> dict[str, Any]:
        from src.integrations.cloudflare_client import CloudflareClient
        return await CloudflareClient().create_dns_record(zone_id, record)
