"""cf_api.py - Cloudflare DNS API wrapper (fixed)."""
import requests, json, time

CF_BASE = "https://api.cloudflare.com/client/v4"

class CloudflareAPI:
    def __init__(self, token):
        self.token = token
        self.headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}
        self.last_error = None

    def _get(self, path, params=None):
        r = requests.get(f"{CF_BASE}{path}", headers=self.headers, params=params, timeout=30)
        return r.status_code, r.json()

    def _post(self, path, body=None):
        r = requests.post(f"{CF_BASE}{path}", headers=self.headers, json=body, timeout=30)
        return r.status_code, r.json()

    def _delete(self, path):
        r = requests.delete(f"{CF_BASE}{path}", headers=self.headers, timeout=30)
        return r.status_code, r.json()

    def verify_token(self):
        code, data = self._get("/user/tokens/verify")
        return data.get("success", False)

    def get_zones(self):
        zones = []
        page = 1
        self.last_error = None
        while True:
            code, data = self._get("/zones", {"page": page, "per_page": 50})
            if not data.get("success"):
                self.last_error = data.get("errors", [{"message": "unknown"}])
                break
            zones.extend(data.get("result", []))
            if page >= data.get("result_info", {}).get("total_pages", 1):
                break
            page += 1
        return zones

    def find_zone_for_domain(self, domain, zones=None):
        if zones is None:
            zones = self.get_zones()
        parts = domain.split(".")
        for i in range(len(parts) - 1):
            test = ".".join(parts[i:])
            for z in zones:
                if z["name"] == test:
                    return z
        return None

    def write_dns_records(self, zone_id, records):
        """records: list of {type, name, content, ttl, priority?}"""
        results = []
        for rec in records:
            body = {
                "type": rec["type"],
                "name": rec["name"],
                "content": rec["content"],
                "ttl": rec.get("ttl", 3600),
                "proxied": False,
            }
            if "priority" in rec:
                body["priority"] = rec["priority"]
            code, data = self._post(f"/zones/{zone_id}/dns_records", body)
            result_obj = {
                "type": rec["type"],
                "name": rec["name"],
                "success": data.get("success", False),
                "id": (data.get("result") or {}).get("id", ""),
                "error": data.get("errors", []),
            }
            if not data.get("success"):
                self.last_error = data.get("errors", [])
            results.append(result_obj)
            time.sleep(0.2)
        return results

    def build_dns_records(self, hostname, ip, dkim_selectors, dmarc_policy, spf_qualifier, domain, ipv6=""):
        """Build all DNS records for a deployed mail server (aligned with original panel format)."""
        records = []
        records.append({"type": "A", "name": hostname, "content": ip, "ttl": 3600})
        if ipv6:
            records.append({"type": "AAAA", "name": hostname, "content": ipv6, "ttl": 3600})
        records.append({"type": "MX", "name": hostname, "content": hostname, "priority": 10, "ttl": 3600})
        dmarc_host = f"v=DMARC1; p={dmarc_policy}; sp=none; adkim=s; aspf=s; pct=100; fo=1; rua=mailto:admin@{hostname}; ruf=mailto:admin@{hostname}"
        records.append({"type": "TXT", "name": f"_dmarc.{hostname}", "content": dmarc_host, "ttl": 3600})
        dmarc_root = f"v=DMARC1; p={dmarc_policy}; sp=none; adkim=s; aspf=s; pct=100; fo=1; rua=mailto:admin@{domain}; ruf=mailto:admin@{domain}"
        records.append({"type": "TXT", "name": f"_dmarc.{domain}", "content": dmarc_root, "ttl": 3600})
        spf_rec = f"v=spf1 mx a ip4:{ip}"
        if ipv6:
            spf_rec += f" ip6:{ipv6}"
        spf_rec += f" {spf_qualifier}"
        records.append({"type": "TXT", "name": hostname, "content": spf_rec, "ttl": 3600})
        for sel_info in dkim_selectors:
            records.append({
                "type": "TXT",
                "name": f"{sel_info['selector']}._domainkey.{hostname}",
                "content": f"v=DKIM1; k=rsa; h=sha256; p={sel_info['public_key']}",
                "ttl": 600,
            })
        for sub in ["imap", "smtp", "pop3"]:
            records.append({"type": "CNAME", "name": f"{sub}.{domain}", "content": hostname, "ttl": 3600})
        return records

    def list_dns_records(self, zone_id):
        records = []
        page = 1
        self.last_error = None
        while True:
            code, data = self._get(f"/zones/{zone_id}/dns_records", {"page": page, "per_page": 100})
            if not data.get("success"):
                self.last_error = data.get("errors", [{"message": "unknown"}])
                break
            records.extend(data.get("result", []))
            if page >= data.get("result_info", {}).get("total_pages", 1):
                break
            page += 1
        return records

    def clear_dns_records(self, zone_id, domain_prefix):
        """Delete all DNS records with names containing domain_prefix."""
        records = self.list_dns_records(zone_id)
        if self.last_error:
            return -1  # signal error
        deleted = 0
        for rec in records:
            if domain_prefix in rec.get("name", ""):
                code, data = self._delete(f"/zones/{zone_id}/dns_records/{rec['id']}")
                if data.get("success"):
                    deleted += 1
                else:
                    self.last_error = data.get("errors", [])
                time.sleep(0.1)
        return deleted
