#!/usr/bin/env python3
import json
import re
import sys
from html.parser import HTMLParser
from urllib.parse import urljoin
from urllib.request import Request, urlopen


EMAIL_RE = re.compile(r"[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}", re.I)
PHONE_RE = re.compile(r"(?:\+?\d[\d\s().-]{7,}\d)")
HREF_RE = re.compile(r"""href=["']([^"']+)["']""", re.I)
SOCIAL_HOST_RE = re.compile(r"(linkedin\.com|facebook\.com|instagram\.com|twitter\.com|x\.com|tiktok\.com)", re.I)


class TextParser(HTMLParser):
    def __init__(self):
        super().__init__()
        self.title = ""
        self._in_title = False
        self.parts = []
        self.links = []

    def handle_starttag(self, tag, attrs):
        self._in_title = tag.lower() == "title"
        if tag.lower() == "a":
            attrs = dict(attrs)
            href = attrs.get("href", "")
            if href:
                self.links.append(href)

    def handle_endtag(self, tag):
        if tag.lower() == "title":
            self._in_title = False

    def handle_data(self, data):
        text = " ".join(data.split())
        if not text:
            return
        if self._in_title:
            self.title = (self.title + " " + text).strip()
        self.parts.append(text)


def normalize_links(base_url, links):
    out = []
    seen = set()
    for raw in links or []:
        href = (raw or "").strip()
        if not href or href.startswith(("mailto:", "tel:", "javascript:", "#")):
            continue
        absolute = urljoin(base_url, href)
        if absolute in seen:
            continue
        seen.add(absolute)
        out.append(absolute)
    return out[:80]


def social_links(links):
    return [link for link in links if SOCIAL_HOST_RE.search(link)][:30]


def extract_links_from_html(html):
    return HREF_RE.findall(html or "")


def fetch_with_scrapling(url, mode, timeout):
    from scrapling.fetchers import Fetcher, DynamicFetcher, StealthyFetcher

    if mode == "dynamic":
        page = DynamicFetcher.fetch(url, headless=True, network_idle=True, timeout=timeout * 1000)
    elif mode == "stealth":
        StealthyFetcher.adaptive = True
        page = StealthyFetcher.fetch(url, headless=True, network_idle=True, timeout=timeout * 1000)
    else:
        page = Fetcher.get(url, timeout=timeout)

    title = ""
    try:
        title = page.css("title::text").get() or ""
    except Exception:
        title = ""
    html = ""
    try:
        html = page.html_content or ""
    except Exception:
        html = ""
    try:
        text = page.get_all_text()
    except Exception:
        text = html or str(page.body)
    return text, title, True, normalize_links(url, extract_links_from_html(html))


def fetch_basic(url, timeout):
    req = Request(url, headers={"User-Agent": "HermesLeadBot/0.1 (+local workflow)"})
    with urlopen(req, timeout=timeout) as response:
        body = response.read(1_000_000).decode("utf-8", errors="ignore")
    parser = TextParser()
    parser.feed(body)
    return " ".join(parser.parts), parser.title, False, normalize_links(url, parser.links)


def main():
    payload = json.loads(sys.stdin.read() or "{}")
    url = payload.get("url", "")
    mode = payload.get("mode", "simple")
    timeout = int(payload.get("timeout", 25))
    if not url:
        print(json.dumps({"ok": False, "error": "missing url", "emails": [], "phones": [], "text": ""}))
        return

    try:
        try:
            text, title, used_scrapling, links = fetch_with_scrapling(url, mode, timeout)
        except ImportError:
            text, title, used_scrapling, links = fetch_basic(url, timeout)

        emails = sorted(set(EMAIL_RE.findall(text)))[:10]
        phones = sorted(set(p.strip() for p in PHONE_RE.findall(text) if len(re.sub(r"\D", "", p)) >= 7))[:10]
        print(json.dumps({
            "ok": True,
            "mode": mode,
            "title": title,
            "emails": emails,
            "phones": phones,
            "links": links,
            "socialLinks": social_links(links),
            "text": text[:12000],
            "usedScrapling": used_scrapling
        }))
    except Exception as exc:
        print(json.dumps({
            "ok": False,
            "mode": mode,
            "error": str(exc),
            "emails": [],
            "phones": [],
            "links": [],
            "socialLinks": [],
            "text": ""
        }))


if __name__ == "__main__":
    main()
