"""Reconcile P2HS-owned domain registration and renewal state."""
from __future__ import annotations

import logging
from datetime import datetime, timedelta, timezone

from sqlalchemy import select

from src.config import get_settings
from src.core.database import async_session_factory
from src.domain.domains.models import DomainEvent, DomainOrder, WorkspaceDomain
from src.domain.domains.providers import CloudflareRegistrarProvider

log = logging.getLogger(__name__)


def _as_utc(value: datetime | None) -> datetime | None:
    if value is None:
        return None
    return value if value.tzinfo else value.replace(tzinfo=timezone.utc)


async def reconcile_domain_renewals(ctx: dict) -> dict:
    """Converge registrar status and auto-renew to Core's billing authorization."""
    settings = get_settings()
    if not settings.domain_registrar_transactions_enabled:
        return {"skipped": True, "reason": "registrar_transactions_disabled"}

    now = datetime.now(timezone.utc)
    renewal_window = now + timedelta(days=settings.domain_renewal_lead_days)
    provider_charge_cutoff = now + timedelta(days=settings.domain_renewal_failure_cutoff_days)
    provider = CloudflareRegistrarProvider()
    reconciled = 0
    changed = 0
    async with async_session_factory() as db:
        domains = list((await db.scalars(select(WorkspaceDomain).where(
            WorkspaceDomain.registrar_provider == "cloudflare_registrar",
            WorkspaceDomain.registration_status.in_(("pending", "active")),
        ))).all())

        for domain in domains:
            if domain.registration_status == "pending":
                try:
                    status = await provider.get_registration_status(domain.normalized_domain)
                    state = str(status.get("status") or status.get("state") or "").lower()
                    if state in {"succeeded", "active", "completed"}:
                        registration = await provider.get_registration(domain.normalized_domain)
                        domain.registration_status = "active"
                        domain.expires_at = _parse_provider_datetime(registration.get("expires_at"))
                        domain.auto_renew = registration.get("auto_renew", domain.auto_renew)
                        domain.registrar_lock_status = registration.get("locked", domain.registrar_lock_status)
                        changed += 1
                    elif state in {"failed", "blocked"}:
                        domain.registration_status = "failed"
                        changed += 1
                except Exception as exc:
                    log.warning("domain_registration_reconcile_failed domain=%s error=%s", domain.normalized_domain, exc)

            expires_at = _as_utc(domain.expires_at)
            if not expires_at or expires_at > renewal_window:
                continue

            order = await db.scalar(select(DomainOrder).where(
                DomainOrder.domain_id == domain.id,
                DomainOrder.stripe_subscription_id.is_not(None),
                DomainOrder.fulfillment_status.in_(("active", "completed")),
            ).order_by(DomainOrder.created_at.desc()))
            authorized = bool(domain.renewal_authorized and order and order.payment_status == "paid")
            # Keep a still-authorized domain enabled throughout the lead window,
            # but do not disable an unauthorized domain until just before the
            # registrar's expected renewal charge window.
            if not authorized and expires_at > provider_charge_cutoff:
                reconciled += 1
                continue
            if domain.auto_renew == authorized:
                reconciled += 1
                continue

            try:
                await provider.set_auto_renew(domain.normalized_domain, authorized)
                domain.auto_renew = authorized
                db.add(DomainEvent(
                    workspace_id=domain.workspace_id,
                    domain_id=domain.id,
                    event_type="domain.renewal_enabled" if authorized else "domain.renewal_disabled",
                    payload_json={"expires_at": expires_at.isoformat(), "authorized": authorized},
                ))
                changed += 1
            except Exception as exc:
                log.error("domain_auto_renew_reconcile_failed domain=%s enabled=%s error=%s", domain.normalized_domain, authorized, exc)
            reconciled += 1

        await db.commit()
    return {"skipped": False, "reconciled": reconciled, "changed": changed}


def _parse_provider_datetime(value: str | None) -> datetime | None:
    if not value:
        return None
    return datetime.fromisoformat(value.replace("Z", "+00:00"))
