"""
TLD Matrix analyzer (open-data).

We check availability for the same SLD across a small, curated TLD set.
This is intentionally small to keep the UX fast.
"""

from __future__ import annotations

import asyncio
from dataclasses import dataclass

from app.services.domain_checker import domain_checker


DEFAULT_TLDS = ["com", "net", "org", "io", "ai", "co", "ch"]


@dataclass(frozen=True)
class TldMatrixRow:
    tld: str
    domain: str
    is_available: bool | None
    status: str  # available|taken|unknown
    method: str
    error: str | None = None


async def _check_one(domain: str) -> TldMatrixRow:
    try:
        res = await domain_checker.check_domain(domain, quick=True)
        return TldMatrixRow(
            tld=domain.split(".")[-1],
            domain=domain,
            is_available=bool(res.is_available),
            status="available" if res.is_available else "taken",
            method=str(res.check_method or "dns"),
            error=res.error_message,
        )
    except Exception as e:  # noqa: BLE001
        return TldMatrixRow(
            tld=domain.split(".")[-1],
            domain=domain,
            is_available=None,
            status="unknown",
            method="error",
            error=str(e),
        )


async def run_tld_matrix(domain: str, tlds: list[str] | None = None, original_is_taken: bool = False) -> list[TldMatrixRow]:
    """
    Check availability for the same SLD across multiple TLDs.
    
    Args:
        domain: The full domain being analyzed (e.g., "akaya.ch")
        tlds: List of TLDs to check (defaults to DEFAULT_TLDS)
        original_is_taken: If True, force the original domain's TLD to show as taken
    """
    parts = (domain or "").lower().strip().split(".")
    sld = parts[0] if parts else ""
    original_tld = parts[-1] if len(parts) > 1 else ""
    tlds = [t.lower().lstrip(".") for t in (tlds or DEFAULT_TLDS)]

    # Avoid repeated checks
    seen = set()
    candidates: list[str] = []
    for t in tlds:
        d = f"{sld}.{t}"
        if d not in seen:
            candidates.append(d)
            seen.add(d)

    rows = await asyncio.gather(*[_check_one(d) for d in candidates])
    result = list(rows)
    
    # If the original domain is known to be taken, ensure its TLD shows as taken
    # This fixes cases where DNS-based quick checks incorrectly show "available"
    # for domains that are registered but have no DNS records
    if original_is_taken and original_tld:
        result = [
            TldMatrixRow(
                tld=r.tld,
                domain=r.domain,
                is_available=False,
                status="taken",
                method=r.method,
                error=r.error,
            ) if r.tld == original_tld else r
            for r in result
        ]
    
    return result

