import re
import logging
import requests
import whois
import tldextract
import phonenumbers
from bs4 import BeautifulSoup
from typing import Dict, List, Set
from urllib.parse import urljoin

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

class LeadEnricher:
    def __init__(self, hunter_api_key: str = None):
        self.timeout = 10
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
        }
        self.hunter_api_key = hunter_api_key
        self.target_subpages = ['/contact', '/about', '/privacy-policy', '/contact-us']

    def _get_domain(self, url: str) -> str:
        ext = tldextract.extract(url)
        return f"{ext.domain}.{ext.suffix}"

    def _validate_phones(self, text: str, region: str = "IN") -> List[str]:
        validated = set()
        for match in phonenumbers.PhoneNumberMatcher(text, region):
            if phonenumbers.is_valid_number(match.number):
                formatted = phonenumbers.format_number(match.number, phonenumbers.PhoneNumberFormat.E164)
                validated.add(formatted)
        return list(validated)

    def _validate_whatsapp(self, raw_numbers: List[str], region: str = "IN") -> List[str]:
        validated_wa = set()
        for raw in raw_numbers:
            try:
                parse_target = f"+{raw}" if not raw.startswith('+') else raw
                parsed_num = phonenumbers.parse(parse_target, region)
                if phonenumbers.is_valid_number(parsed_num):
                    validated_wa.add(phonenumbers.format_number(parsed_num, phonenumbers.PhoneNumberFormat.E164))
            except: continue
        return list(validated_wa)

    def get_whois_emails(self, domain: str) -> List[str]:
        """Layer 3: Extract administrative/registrant emails from WHOIS records."""
        try:
            w = whois.whois(domain)
            emails = w.emails
            if not emails: return []
            
            # Normalize to list
            found = emails if isinstance(emails, list) else [emails]
            
            # Filter out common domain privacy protection emails
            filtered = [
                e.lower() for e in found 
                if not any(x in e.lower() for x in ['privacy', 'proxy', 'abuse', 'domainsbyproxy'])
            ]
            return list(set(filtered))
        except Exception as e:
            logger.debug(f"WHOIS lookup failed for {domain}: {e}")
            return []

    def crawl_site(self, base_url: str) -> Dict:
        if not base_url.startswith('http'):
            base_url = 'https://' + base_url
            
        urls_to_scan = [base_url] + [urljoin(base_url, p) for p in self.target_subpages]
        
        aggregated_data = {
            "emails": set(),
            "phones": set(),
            "whatsapp": set(),
            "socials": set()
        }

        for url in list(dict.fromkeys(urls_to_scan)):
            try:
                res = requests.get(url, headers=self.headers, timeout=self.timeout)
                if res.status_code != 200: continue
                
                soup = BeautifulSoup(res.text, 'html.parser')
                html_str = res.text
                
                for noise in soup(["script", "style"]):
                    noise.decompose()
                clean_text = soup.get_text(separator=' ')

                # 1. Emails (Regex)
                aggregated_data["emails"].update(re.findall(r'[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}', html_str))

                # 2. Phones (phonenumbers validator)
                aggregated_data["phones"].update(self._validate_phones(clean_text))

                # 3. WhatsApp (Cross-validated with phonenumbers)
                raw_wa = re.findall(r'(?:wa\.me|api\.whatsapp\.com/send\?phone=)(\d+)', html_str)
                aggregated_data["whatsapp"].update(self._validate_whatsapp(raw_wa))

                # 4. Socials
                social_patterns = r'https?://(?:www\.)?(?:facebook|instagram|linkedin|twitter|tiktok)\.com/[a-zA-Z0-9._%-]+'
                aggregated_data["socials"].update([s for s in re.findall(social_patterns, html_str) if 'sharer' not in s])

            except Exception as e:
                logger.error(f"Error crawling {url}: {e}")

        return {k: list(v) for k, v in aggregated_data.items()}

    def process_target(self, url: str):
        domain = self._get_domain(url)
        logger.info(f"Processing lead for: {domain}")

        # Step 1: Site Crawl
        site_data = self.crawl_site(url)
        
        # Step 2: WHOIS Layer
        whois_emails = self.get_whois_emails(domain)
        site_data["emails"] = list(set(site_data["emails"]) | set(whois_emails))

        # Step 3: Final Validation & Formatting
        site_data["phones"] = list(set(site_data["phones"]) | set(site_data["whatsapp"]))

        return {
            "domain": domain,
            "extracted_data": site_data,
            "confidence_score": self._calculate_confidence(site_data)
        }

    def _calculate_confidence(self, data: Dict) -> int:
        score = 0
        if data["emails"]: score += 40
        if data["whatsapp"]: score += 40
        if data["phones"]: score += 20
        return min(score, 100)