"""DNS resolution and analysis."""
import asyncio
from typing import Dict, List, Optional

import dns.resolver
from dns.exception import DNSException

from reclaimor.config import Config
from reclaimor.utils.logger import setup_logger

logger = setup_logger(__name__)


class DNSChecker:
    """DNS resolution and CNAME analysis."""
    
    def __init__(self, config: Config):
        self.config = config
        self.resolver = dns.resolver.Resolver()
        self.resolver.timeout = config.timeout
        self.resolver.lifetime = config.timeout
    
    async def check(self, domain: str) -> Dict:
        """
        Perform DNS checks on domain.
        
        Returns dict with:
            - resolvable: bool
            - cname: str or None
            - records: dict of record types to values
            - error: str or None
        """
        result = {
            "resolvable": False,
            "cname": None,
            "records": {},
            "error": None,
        }
        
        try:
            # Check CNAME
            cname = await self._resolve_cname(domain)
            if cname:
                result["cname"] = cname
                result["records"]["CNAME"] = [cname]
            
            # Check A records
            a_records = await self._resolve_a(domain)
            if a_records:
                result["records"]["A"] = a_records
                result["resolvable"] = True
            
            # Check AAAA records
            aaaa_records = await self._resolve_aaaa(domain)
            if aaaa_records:
                result["records"]["AAAA"] = aaaa_records
                result["resolvable"] = True
            
            # If we have CNAME but no A/AAAA, it's a dangling CNAME
            if cname and not result["resolvable"]:
                result["resolvable"] = False
                result["error"] = "Dangling CNAME - potential takeover"
        
        except Exception as e:
            logger.debug(f"DNS check error for {domain}: {e}")
            result["error"] = str(e)
        
        return result
    
    async def _resolve_cname(self, domain: str) -> Optional[str]:
        """Resolve CNAME record."""
        try:
            loop = asyncio.get_event_loop()
            answers = await loop.run_in_executor(
                None, self.resolver.resolve, domain, "CNAME"
            )
            if answers:
                return str(answers[0].target).rstrip(".")
        except DNSException:
            pass
        return None
    
    async def _resolve_a(self, domain: str) -> List[str]:
        """Resolve A records."""
        try:
            loop = asyncio.get_event_loop()
            answers = await loop.run_in_executor(
                None, self.resolver.resolve, domain, "A"
            )
            return [str(rdata) for rdata in answers]
        except DNSException:
            return []
    
    async def _resolve_aaaa(self, domain: str) -> List[str]:
        """Resolve AAAA records."""
        try:
            loop = asyncio.get_event_loop()
            answers = await loop.run_in_executor(
                None, self.resolver.resolve, domain, "AAAA"
            )
            return [str(rdata) for rdata in answers]
        except DNSException:
            return []
