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 SpaceshipIntegration(RegistrarBase):
    """
    Spaceship Official REST API Integration.
    Based on Spaceship OpenAPI v1.0.0 specification:
    - Base URL: https://spaceship.dev/api/v1
    - Headers: X-API-Key and X-API-Secret
    """

    BASE_URL = "https://spaceship.dev/api/v1"

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

    def _headers(self) -> Dict[str, str]:
        return {
            "X-API-Key": self.api_key,
            "X-API-Secret": self.api_secret,
            "Content-Type": "application/json",
            "Accept": "application/json",
        }

    async def test_connection(self) -> bool:
        """
        Verify API credentials by querying the domain list endpoint with take=1.
        """
        if not self.api_key or not self.api_secret:
            raise ValueError("Both Spaceship API Key and API Secret are required.")

        async with httpx.AsyncClient(timeout=12.0) as client:
            resp = await client.get(
                f"{self.BASE_URL}/domains",
                headers=self._headers(),
                params={"take": 1, "skip": 0},
            )
            if resp.status_code == 200:
                return True
            elif resp.status_code in (401, 403):
                detail = "Unauthorized"
                try:
                    detail = resp.json().get("detail", detail)
                except Exception:
                    pass
                raise ValueError(f"Spaceship authentication failed: {detail}")
            else:
                raise ValueError(f"Spaceship API responded with status {resp.status_code}: {resp.text}")

    async def list_domains(self) -> List[Dict[str, Any]]:
        """
        Fetch all registered domains from Spaceship with pagination.
        GET /v1/domains?take=100&skip={skip}
        """
        domains: List[Dict[str, Any]] = []
        skip = 0
        take = 100

        async with httpx.AsyncClient(timeout=20.0) as client:
            while True:
                resp = await client.get(
                    f"{self.BASE_URL}/domains",
                    headers=self._headers(),
                    params={"take": take, "skip": skip},
                )
                if resp.status_code != 200:
                    logger.error(f"Failed to list Spaceship domains: {resp.status_code} {resp.text}")
                    break

                data = resp.json()
                items = data.get("items", [])
                total = data.get("total", len(items))

                for item in items:
                    domain_name = item.get("name") or item.get("unicodeName")
                    if not domain_name:
                        continue

                    # Parse expirationDate (ISO-8601 UTC)
                    expiry_raw = item.get("expirationDate")
                    expiry_date: Optional[date] = None
                    if expiry_raw:
                        try:
                            expiry_date = datetime.fromisoformat(expiry_raw.replace("Z", "+00:00")).date()
                        except Exception:
                            pass

                    # Status mapping from lifecycleStatus ('registered', 'grace1', 'grace2', 'redemption', 'creating')
                    lifecycle = item.get("lifecycleStatus", "registered")
                    status = "active"
                    if lifecycle in ("grace1", "grace2", "redemption"):
                        status = "expired"
                    elif lifecycle == "creating":
                        status = "pending"

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

                skip += take
                if skip >= total or not items:
                    break

        return domains

    async def get_dns_records(self, domain_name: str) -> List[Dict[str, Any]]:
        """
        Fetch DNS records for a domain from Spaceship.
        GET /v1/dns/records/{domain}?take=500&skip=0
        """
        records: List[Dict[str, Any]] = []
        skip = 0
        take = 100

        async with httpx.AsyncClient(timeout=20.0) as client:
            while True:
                resp = await client.get(
                    f"{self.BASE_URL}/dns/records/{domain_name.lower().strip()}",
                    headers=self._headers(),
                    params={"take": take, "skip": skip},
                )
                if resp.status_code != 200:
                    logger.warning(f"Spaceship get_dns_records failed for {domain_name}: {resp.status_code} {resp.text}")
                    break

                data = resp.json()
                items = data.get("items", [])
                total = data.get("total", len(items))

                for r in items:
                    rec_type = r.get("type", "A").upper()
                    name = r.get("name", "@")
                    ttl = r.get("ttl", 3600)
                    priority = None
                    value = ""

                    # Spaceship OpenAPI returns specific fields per record type
                    if rec_type in ("A", "AAAA"):
                        value = r.get("address", "")
                    elif rec_type == "CNAME":
                        value = r.get("cname", "")
                    elif rec_type == "ALIAS":
                        value = r.get("aliasName", "")
                    elif rec_type == "MX":
                        value = r.get("exchange", "")
                        priority = r.get("preference")
                    elif rec_type == "TXT":
                        value = r.get("value", "")
                    elif rec_type == "NS":
                        value = r.get("nameserver", "")
                    elif rec_type == "SRV":
                        value = f"{r.get('target', '')}:{r.get('port', '')}"
                        priority = r.get("priority")
                    elif rec_type == "CAA":
                        value = f"{r.get('flag', 0)} {r.get('tag', '')} {r.get('value', '')}"
                    elif rec_type == "PTR":
                        value = r.get("pointer", "")
                    else:
                        value = r.get("value") or r.get("address") or r.get("cname") or str(r)

                    records.append({
                        "record_type": rec_type,
                        "name": name,
                        "value": value,
                        "ttl": ttl,
                        "priority": priority,
                    })

                skip += take
                if skip >= total or not items:
                    break

        return records
