# retoor <retoor@molodetz.nl>
from __future__ import annotations

from typing import Callable
from urllib.parse import urlparse

from devplacepy.services.jobs.isslop.analysis.domsignals.base import DomPageContext, dom_check
from devplacepy.services.jobs.isslop.analysis.signals import (
    AXIS_ORIGIN,
    SEVERITY_MEDIUM,
    SEVERITY_STRONG,
    SEVERITY_WEAK,
    Signal,
)

CLAUDE_ARTIFACT_BADGE_KEY: str = 'iframe[src*="claudeusercontent.com"]'

FRAMER_RESOURCE_HOSTS: frozenset[str] = frozenset(
    {"events.framer.com", "framerusercontent.com", "framercdn.com", "framercanvas.com"}
)
WIX_RESOURCE_HOSTS: frozenset[str] = frozenset(
    {"static.wixstatic.com", "static.parastorage.com", "siteassets.parastorage.com"}
)
WEBFLOW_RESOURCE_HOSTS: frozenset[str] = frozenset(
    {"assets-global.website-files.com", "uploads-ssl.webflow.com", "assets.website-files.com"}
)
SQUARESPACE_RESOURCE_HOSTS: frozenset[str] = frozenset(
    {"static1.squarespace.com", "static.squarespace.com", "images.squarespace-cdn.com"}
)
HOSTING_HEADER_KEYS: frozenset[str] = frozenset({"x-vercel-id", "x-nf-request-id"})


def _host_of(url: str) -> str:
    return (urlparse(url).hostname or "").lower()


def _resource_text(page: DomPageContext) -> str:
    scripts = page.dom.get("scripts", []) or []
    links = page.dom.get("links", []) or []
    hosts = page.resource_hosts or []
    return " ".join(str(item) for item in (*scripts, *links, *hosts)).lower()


def _generator(page: DomPageContext) -> str:
    meta = page.dom.get("meta", {}) or {}
    return str(meta.get("generator") or "")


def _class_names(page: DomPageContext) -> list[str]:
    return list((page.dom.get("classNames") or {}).keys())


def _badge(page: DomPageContext, selector: str) -> bool:
    return bool((page.dom.get("badgeHits") or {}).get(selector))


def _detect_lovable(page: DomPageContext) -> Signal | None:
    badge = _badge(page, "#lovable-badge")
    resource_hit = "cdn.gpteng.co" in _resource_text(page) or "gptengineer.js" in _resource_text(page)
    generator_hit = "lovable" in _generator(page).lower()
    host_hit = _host_of(page.url).endswith(".lovable.app")
    if not (badge or resource_hit or generator_hit or host_hit):
        return None
    evidence = "lovable-badge" if badge else "cdn.gpteng.co" if resource_hit else "generator meta" if generator_hit else "lovable.app host"
    return Signal("AI_BUILDER_LOVABLE", "Lovable / GPT Engineer builder fingerprint", SEVERITY_STRONG, AXIS_ORIGIN, 4.0, 0, evidence)


def _detect_bolt(page: DomPageContext) -> Signal | None:
    haystack = _resource_text(page) + " " + page.url.lower()
    if "bolt.new" not in haystack:
        return None
    return Signal("AI_BUILDER_BOLT", "Bolt.new builder fingerprint", SEVERITY_STRONG, AXIS_ORIGIN, 4.0, 0, "bolt.new")


def _detect_replit(page: DomPageContext) -> Signal | None:
    badge = _badge(page, ".replit-badge")
    host = _host_of(page.url)
    host_hit = host.endswith(".replit.app") or host.endswith(".repl.co")
    if not (badge or host_hit):
        return None
    return Signal("AI_BUILDER_REPLIT", "Replit builder fingerprint", SEVERITY_STRONG, AXIS_ORIGIN, 4.0, 0, "replit-badge" if badge else host)


def _detect_base44(page: DomPageContext) -> Signal | None:
    if not _badge(page, "#base44-badge"):
        return None
    return Signal("AI_BUILDER_BASE44", "Base44 builder fingerprint", SEVERITY_STRONG, AXIS_ORIGIN, 4.0, 0, "base44-badge")


def _detect_framer(page: DomPageContext) -> Signal | None:
    badge = _badge(page, "#__framer-badge-container")
    generator_hit = "framer" in _generator(page).lower()
    resource_hit = bool(set(page.resource_hosts or []) & FRAMER_RESOURCE_HOSTS)
    host_hit = _host_of(page.url).endswith(".framer.website")
    if not (badge or generator_hit or resource_hit or host_hit):
        return None
    evidence = "framer-badge" if badge else "generator meta" if generator_hit else "framer resource host" if resource_hit else "framer.website host"
    return Signal("AI_BUILDER_FRAMER", "Framer builder fingerprint", SEVERITY_STRONG, AXIS_ORIGIN, 4.0, 0, evidence)


def _detect_wix(page: DomPageContext) -> Signal | None:
    generator_hit = "wix.com website builder" in _generator(page).lower()
    resource_hit = bool(set(page.resource_hosts or []) & WIX_RESOURCE_HOSTS)
    class_hit = any("wix-bolt" in name.lower() for name in _class_names(page))
    if not (generator_hit or resource_hit or class_hit):
        return None
    evidence = "generator meta" if generator_hit else "wix resource host" if resource_hit else "wix-bolt class"
    return Signal("AI_BUILDER_WIX", "Wix builder fingerprint", SEVERITY_STRONG, AXIS_ORIGIN, 4.0, 0, evidence)


def _detect_webflow(page: DomPageContext) -> Signal | None:
    generator_hit = "webflow" in _generator(page).lower()
    resource_hit = bool(set(page.resource_hosts or []) & WEBFLOW_RESOURCE_HOSTS)
    if not (generator_hit or resource_hit):
        return None
    return Signal("AI_BUILDER_WEBFLOW", "Webflow builder fingerprint", SEVERITY_STRONG, AXIS_ORIGIN, 4.0, 0, "generator meta" if generator_hit else "webflow resource host")


def _detect_godaddy(page: DomPageContext) -> Signal | None:
    if "go daddy website builder" not in _generator(page).lower():
        return None
    return Signal("AI_BUILDER_GODADDY", "GoDaddy Website Builder fingerprint", SEVERITY_STRONG, AXIS_ORIGIN, 4.0, 0, "generator meta")


def _detect_squarespace(page: DomPageContext) -> Signal | None:
    resource_hit = bool(set(page.resource_hosts or []) & SQUARESPACE_RESOURCE_HOSTS)
    class_hit = any(name.lower().startswith("sqs-block") or name.lower().startswith("yui3-") for name in _class_names(page))
    if not (resource_hit or class_hit):
        return None
    return Signal("AI_BUILDER_SQUARESPACE", "Squarespace builder fingerprint", SEVERITY_STRONG, AXIS_ORIGIN, 4.0, 0, "squarespace resource host" if resource_hit else "sqs-block class")


def _detect_claude_artifact(page: DomPageContext) -> Signal | None:
    if not _badge(page, CLAUDE_ARTIFACT_BADGE_KEY):
        return None
    return Signal("AI_BUILDER_CLAUDE_ARTIFACT", "Claude Artifacts iframe embed detected", SEVERITY_STRONG, AXIS_ORIGIN, 4.0, 0, "claudeusercontent.com iframe")


def _detect_shadcn_radix_cluster(page: DomPageContext) -> Signal | None:
    indicators: list[str] = []
    if _badge(page, "[data-radix-root]"):
        indicators.append("data-radix-root")
    if any("radix" in name.lower() for name in _class_names(page)):
        indicators.append("radix class token")
    if "lucide" in _resource_text(page):
        indicators.append("lucide icons")
    if len(indicators) < 2:
        return None
    severity = SEVERITY_STRONG if len(indicators) >= 3 else SEVERITY_MEDIUM
    return Signal("SHADCN_RADIX_CLUSTER", f"shadcn/ui and Radix primitives cluster ({len(indicators)} indicators)", severity, AXIS_ORIGIN, 3.0, 0, ", ".join(indicators))


def _detect_hosting_subdomain(page: DomPageContext) -> Signal | None:
    host = _host_of(page.url)
    host_hit = host.endswith(".vercel.app") or host.endswith(".netlify.app") or host.endswith(".databutton.app")
    headers = {key.lower() for key in (page.response_headers or {}).keys()}
    header_hit = bool(headers & HOSTING_HEADER_KEYS)
    if not (host_hit or header_hit):
        return None
    evidence = host if host_hit else ", ".join(sorted(headers & HOSTING_HEADER_KEYS))
    return Signal("BUILDER_HOSTING_SUBDOMAIN", "Hosted on a default builder/PaaS subdomain", SEVERITY_WEAK, AXIS_ORIGIN, 1.0, 0, evidence)


_VENDOR_DETECTORS: tuple[tuple[Callable[[DomPageContext], Signal | None], str], ...] = (
    (_detect_lovable, "Lovable"),
    (_detect_bolt, "Bolt.new"),
    (_detect_replit, "Replit"),
    (_detect_base44, "Base44"),
    (_detect_framer, "Framer"),
    (_detect_wix, "Wix"),
    (_detect_webflow, "Webflow"),
    (_detect_godaddy, "GoDaddy"),
    (_detect_squarespace, "Squarespace"),
    (_detect_claude_artifact, "Claude Artifacts"),
)


@dom_check
def detect_builders(page: DomPageContext) -> list[Signal]:
    findings: list[Signal] = []
    for detector, _label in _VENDOR_DETECTORS:
        signal = detector(page)
        if signal is not None:
            findings.append(signal)
    cluster = _detect_shadcn_radix_cluster(page)
    if cluster is not None:
        findings.append(cluster)
    hosting = _detect_hosting_subdomain(page)
    if hosting is not None:
        findings.append(hosting)
    return findings


def detected_builder(pages: list[DomPageContext]) -> tuple[str | None, float]:
    cluster_hit = False
    for page in pages:
        for detector, label in _VENDOR_DETECTORS:
            if detector(page) is not None:
                return label, 1.0
        if _detect_shadcn_radix_cluster(page) is not None:
            cluster_hit = True
    if cluster_hit:
        return "shadcn/ui + Radix", 0.5
    return None, 0.0
