import logging
from datetime import date, datetime
from typing import Any, Dict, List, Optional
import httpx

from integrations.base import RegistrarBase

logger = logging.getLogger(__name__)


class PorkbunIntegration(RegistrarBase):
    """
    Porkbun REST API Integration.
    API docs: https://porkbun.com/api/json/v3/documentation
    Base URL: https://api.porkbun.com/api/json/v3
    """

    BASE_URL = "https://api.porkbun.com/api/json/v3"

    def __init__(self, credentials: Dict[str, Any]) -> None:
        self.api_key: str = credentials.get("api_key", "").strip()
        self.secret_api_key: str = credentials.get("secret_api_key", "").strip()

    def _auth_payload(self) -> Dict[str, str]:
        return {
            "apikey": self.api_key,
            "secretapikey": self.secret_api_key,
        }

    async def test_connection(self) -> bool:
        """Test credentials via ping endpoint."""
        if not self.api_key or not self.secret_api_key:
            raise ValueError("Both Porkbun API Key and Secret API Key are required.")

        async with httpx.AsyncClient(timeout=10.0) as client:
            resp = await client.post(
                f"{self.BASE_URL}/ping",
                json=self._auth_payload(),
            )
            if resp.status_code == 200:
                data = resp.json()
                if data.get("status") == "SUCCESS":
                    return True
                raise ValueError(f"Porkbun auth error: {data.get('message', 'Failed')}")
            raise ValueError(f"Porkbun HTTP error {resp.status_code}: {resp.text}")

    async def list_domains(self) -> List[Dict[str, Any]]:
        """List all domains from Porkbun: POST /domain/listAll"""
        domains: List[Dict[str, Any]] = []
        async with httpx.AsyncClient(timeout=20.0) as client:
            resp = await client.post(
                f"{self.BASE_URL}/domain/listAll",
                json=self._auth_payload(),
            )
            if resp.status_code != 200:
                logger.error(f"Porkbun listAll failed: {resp.status_code} {resp.text}")
                return domains

            data = resp.json()
            items = data.get("yourDomains", [])
            for item in items:
                domain_name = item.get("domain")
                if not domain_name:
                    continue

                expiry_raw = item.get("expireDate")
                expiry_date: Optional[date] = None
                if expiry_raw:
                    try:
                        expiry_date = datetime.strptime(expiry_raw.split()[0], "%Y-%m-%d").date()
                    except Exception:
                        pass

                domains.append({
                    "domain_name": domain_name.lower().strip(),
                    "expiry_date": expiry_date,
                    "auto_renew": bool(item.get("autoRenew", False) or item.get("autoRenew") == "1"),
                    "status": item.get("status", "active").lower(),
                    "registrar_domain_id": domain_name,
                })

        return domains

    async def get_dns_records(self, domain_name: str) -> List[Dict[str, Any]]:
        """Fetch DNS records from Porkbun: POST /dns/retrieve/{domain}"""
        records: List[Dict[str, Any]] = []
        async with httpx.AsyncClient(timeout=15.0) as client:
            resp = await client.post(
                f"{self.BASE_URL}/dns/retrieve/{domain_name.lower().strip()}",
                json=self._auth_payload(),
            )
            if resp.status_code == 200:
                data = resp.json()
                items = data.get("records", [])
                for r in items:
                    records.append({
                        "record_type": r.get("type", "A").upper(),
                        "name": r.get("name", "@"),
                        "value": r.get("content", ""),
                        "ttl": int(r.get("ttl", 300)),
                        "priority": int(r["prio"]) if "prio" in r and r["prio"] is not None else None,
                    })
        return records
