from __future__ import annotations

import re

ADAPTIVE_RETRY_MIN_WORDS = 20
SCHEMA_FALLBACK_MIN_GAIN = 3

# ─── Removal constants (ported from defuddle) ────────────────────────

MIN_IMAGE_SIZE = 33

# Exact CSS selectors for elements to remove.
# These are high-confidence removals — nav, footer, ads, forms, etc.
EXACT_SELECTORS: list[str] = [
    # scripts, styles
    "noscript",
    "style",
    "meta",
    "link",
    # ads
    ".ad",
    "[role='banner']",
    ".promo",
    ".Promo",
    "#barrier-page",
    # NOTE: .alert excluded — handled by callout normalization in standardize
    # comments
    "#comments",
    "#comment",
    # cover images
    "div[class*='cover-']",
    "div[id*='cover-']",
    # header, nav
    "header",
    ".header",
    "#header",
    "#Header",
    "#banner",
    "#Banner",
    "nav",
    ".navigation",
    "#navigation",
    "[role='navigation']",
    "[role='dialog']",
    "[role='complementary']",
    ".menu",
    "#siteSub",
    ".previous",
    # metadata
    ".author",
    ".Author",
    "#categories",
    ".contributor",
    ".date",
    "#date",
    "[data-date]",
    ".entry-meta",
    ".meta",
    ".tags",
    "#tags",
    "[rel='tag']",
    ".toc",
    ".Toc",
    "#toc",
    ".headline",
    "#headline",
    "#title",
    "#Title",
    "#articleTag",
    "[href*='/tag/']",
    "[href*='/tags/']",
    "[href*='/author/']",
    "[href*='/author?']",
    "[href$='/author']",
    "a[href*='copyright.com']",
    "a[href*='google.com/preferences']",
    "[href*='#toc']",
    "[href='#top']",
    "[href='#Top']",
    "[href='#page-header']",
    "[href='#content']",
    "[href='#site-content']",
    "[href='#main-content']",
    "[src*='author']",
    # footer
    "footer",
    # inputs, forms
    ".aside",
    "aside:not([class*='callout'])",
    "button",
    "canvas",
    "dialog",
    "fieldset",
    "form",
    "input:not([type='checkbox'])",
    "label",
    "option",
    "select",
    "[role='listbox']",
    "[role='option']",
    "textarea",
    # hidden
    "[hidden]",
    # NOTE: aria-hidden handled by hidden.py with math protection; not in selectors
    ".hidden",
    ".invisible",
    # iframes (except video embeds)
    "instaread-player",
    # logos
    "#logo",
    "#Logo",
    # newsletter
    "#newsletter",
    "#Newsletter",
    ".subscribe",
    # print
    ".noprint",
    # footnote citations
    "[class*='clickable-icon']",
    # link lists
    "[data-container*='most-viewed']",
    # sidebar
    ".sidebar",
    ".Sidebar",
    "#sidebar",
    "#Sidebar",
    "#side-bar",
    "#sitesub",
    # skip links
    "[data-link-name*='skip']",
    "[aria-label*='skip']",
    # other
    ".copyright",
    "#copyright",
    ".licensebox",
    "#page-info",
    "#rss",
    "#feed",
    ".gutter",
    "#primaryaudio",
    "#NYT_ABOVE_MAIN_CONTENT_REGION",
    "table.infobox",
    ".gh-header-sticky",
]

# Pre-joined CSS selector for single-query removal (performance optimization).
EXACT_SELECTORS_JOINED: str = ", ".join(EXACT_SELECTORS)

# Partial selector patterns tested against class/id/data-test* attributes.
# Case-insensitive substring matches.
PARTIAL_SELECTOR_PATTERNS: list[str] = [
    "a-statement",
    "access-wall",
    "activitypub",
    "actioncall",
    "addcomment",
    "addtoany",
    "advert",
    "adlayout",
    "ad-tldr",
    "ad-placement",
    "ads-container",
    "_ad_",
    "AdBlock_",
    "AdUnit",
    "after_content",
    "after_main_article",
    "afterpost",
    # NOTE: "-alert-" removed — it false-positives on "markdown-alert" (GitHub
    # callout/admonition classes).  Cookie/banner alerts are covered by
    # "cookie", "-banner-", and the exact ".alert" selector was already
    # excluded in EXACT_SELECTORS for the same reason.
    "alert-box",
    "_archive",
    "around-the-web",
    "article-author",
    "article-badges",
    "article-banner",
    "article-bottom",
    "article-category",
    "article-card",
    "article-citation",
    "article_date",
    "article-date",
    "article_header",
    "article-header",
    "article__header",
    "article__hero",
    "article__info",
    "article-info",
    "article-meta",
    "article_meta",
    "article__meta",
    "article-subject",
    "article-snippet",
    "article-separator",
    "article--share",
    "article--topics",
    "articletags",
    "article-tags",
    "article_tags",
    "articletitle",
    "article-title",
    "article_title",
    "articletopics",
    "article-topics",
    "article-actions",
    "article--lede",
    "articlewell",
    "associated-people",
    "audio-card",
    "author-bio",
    "author-box",
    "author-info",
    "author_info",
    "author-mini-bio",
    "author-name",
    "author-publish-info",
    "authored-by",
    "avatar",
    "back-to-top",
    "backlink_container",
    "backlinks-section",
    "bio-block",
    "biobox",
    "blog-pager",
    "bookmark-",
    "-bookmark",
    "bottominfo",
    "bottomnav",
    "bottom-of-article",
    "bottom-wrapper",
    "brand-bar",
    "bcrumb",
    "breadcrumb",
    "brdcrumb",
    "button-wrapper",
    "buttons-container",
    "btn-",
    "-btn",
    "byline",
    "captcha",
    "card-text",
    "card-media",
    "card-post",
    "carouselcontainer",
    "carousel-container",
    "cat_header",
    "catlinks",
    "_categories",
    "card-author",
    "card-content",
    "chapter-list",
    "collections",
    "comments",
    "-comment",
    "commentbox",
    "comment-button",
    "commentcomp",
    "comment-content",
    "comment-count",
    "comment-form",
    "comment-number",
    "comment-respond",
    "comment-thread",
    "comment-wrap",
    "complementary",
    "consent",
    "contact-",
    "content-card",
    "content-topics",
    "contentpromo",
    "context-bar",
    "context-widget",
    "core-collateral",
    "cover-image",
    "cover-photo",
    "cover-wrap",
    "created-date",
    "creative-commons_",
    "c-subscribe",
    "_cta",
    "-cta",
    "cta-",
    "cta_",
    "current-issue",
    "custom-list-number",
    "dateline",
    "dateheader",
    "date-header",
    "date-pub",
    "disclaimer",
    "disclosure",
    "discussion",
    "discuss_",
    "-dismiss",
    "disqus",
    "donate",
    "donation",
    "dropdown",
    "element-invisible",
    "emailsignup",
    "emoji-bar",
    "engagement-widget",
    "enhancement-",
    "entry-author-info",
    "entry-categories",
    "entry-date",
    "entry-title",
    "entry-utility",
    "-error",
    "error-",
    "eyebrow",
    "expand-reduce",
    "external-anchor",
    "externallinkembedwrapper",
    "extra-services",
    "extra-title",
    "facebook",
    "fancy-box",
    "favorite",
    "featured-content",
    "feature_feed",
    "feedback",
    "feed-links",
    "field-site-sections",
    "fixheader",
    "floating-vid",
    "follower",
    "footer",
    "footnote-back",
    "footnoteback",
    "form-group",
    "for-you",
    "frontmatter",
    "further-reading",
    "fullbleedheader",
    "gallery-count",
    "gated-",
    "gh-feed",
    "gist-meta",
    "goog-",
    "graph-view",
    "hamburger",
    "header_logo",
    "header-logo",
    "header-pattern",
    "hero-list",
    "hide-for-print",
    "hide-print",
    "hide-when-no-script",
    "hidden-print",
    "hidden-sidenote",
    "hidden-accessibility",
    "infoline",
    "inline-topic",
    "interlude",
    "interaction",
    "intro-date",
    "invisible",
    "jp-relatedposts",
    "jswarning",
    "js-warning",
    "jumplink",
    "jumpto",
    "jump-to-",
    "js-skip-to-content",
    "keepreading",
    "keep-reading",
    "keep_reading",
    "keyword_wrap",
    "kicker",
    "labstab",
    "-labels",
    "language-name",
    "lastupdated",
    "latest-content",
    "-ledes-",
    "-license",
    "license-",
    "lightbox-popup",
    "like-button",
    "link-box",
    "links-grid",
    "links-title",
    "listing-dynamic-terms",
    "list-tags",
    "loading",
    "logo_container",
    "ltx_role_refnum",
    "ltx_tag_bibitem",
    "ltx_error",
    "masthead",
    "marketing",
    "media-inquiry",
    "-menu",
    "menu-",
    "metadata",
    "meta-date",
    "meta-row",
    "might-like",
    "minibio",
    "more-about",
    "mod-paywall",
    "_modal",
    "-modal",
    "more-",
    "morenews",
    "morestories",
    "more_wrapper",
    "most-read",
    "move-helper",
    "mw-editsection",
    "mw-cite-backlink",
    "mw-indicators",
    "mw-jump-link",
    "nav-",
    "nav_",
    "navigation-post",
    "next-",
    "newsgallery",
    "news-story-title",
    "newsletter_",
    "newsletterbanner",
    "newslettercontainer",
    "newsletter-form",
    "newsletter-signup",
    "newslettersignup",
    "newsletterwidget",
    "newsletterwrapper",
    "not-found",
    "notessection",
    "nomobile",
    "noprint",
    "open-slideshow",
    "originally-published",
    "other-blogs",
    "outline-view",
    "pagehead",
    "page-header",
    "page-title",
    "paywall_message",
    "-partners",
    "permission-",
    "plea",
    "popular",
    "popup_links",
    "pop_stories",
    "pop-up",
    "post-author",
    "post-bottom",
    "post__category",
    "postcomment",
    "postdate",
    "post-date",
    "post_date",
    "post-details",
    "post-feeds",
    "postinfo",
    "post-info",
    "post_info",
    "post-inline-date",
    "post-links",
    "postlist",
    "post_list",
    "post_meta",
    "post-meta",
    "postmeta",
    "post_more",
    "postnavi",
    "post-navigation",
    "postpath",
    "post-preview",
    "postsnippet",
    "post_snippet",
    "post-snippet",
    "post-subject",
    "posttax",
    "post-tax",
    "post_tax",
    "posttag",
    "post_tag",
    "post-tag",
    "post_time",
    "posttitle",
    "post-title",
    "post_title",
    "post__title",
    "post-ufi-button",
    "prev-post",
    "prevnext",
    "prev_next",
    "prev-next",
    "previousnext",
    "press-inquiries",
    "print-none",
    "print-header",
    "print:hidden",
    "privacy-notice",
    "privacy-settings",
    "profile",
    "promo_article",
    "promo-bar",
    "promo-box",
    "pubdate",
    "pub_date",
    "pub-date",
    "publish_date",
    "publish-date",
    "publication-date",
    "publicationName",
    "qr-code",
    "qr_code",
    "quick_up",
    "_rail",
    "ratingssection",
    "read_also",
    "readmore",
    "read-next",
    "read_next",
    "read_time",
    "read-time",
    "reading_time",
    "reading-time",
    "reading-list",
    "recent-",
    "recent-articles",
    "recentpost",
    "recent_post",
    "recent-post",
    "recommend",
    "redirectedfrom",
    "recirc",
    "register",
    "related",
    "relevant",
    "reversefootnote",
    "robots-nocontent",
    "_rss",
    "rss-link",
    "screen-reader-text",
    "scroll_to",
    "scroll-to",
    "_search",
    "-search",
    "section-nav",
    "series-banner",
    "share-box",
    "sharedaddy",
    "share-icons",
    "sharelinks",
    "share-post",
    "share-print",
    "share-section",
    "shariff-",
    "show-for-print",
    "sidebartitle",
    "sidebar-content",
    "sidebar-wrapper",
    "sideitems",
    "sidebar-author",
    "sidebar-item",
    "side-box",
    "side-logo",
    "sign-in-gate",
    "similar-",
    "similar_",
    "similars-",
    "site-index",
    "site-header",
    "siteheader",
    "site-logo",
    "site-name",
    "site-wordpress",
    "skip-content",
    "skip-to-content",
    "skip-link",
    "c-skip-link",
    "_skip-link",
    "-slider",
    "slug-wrap",
    "social-author",
    "social-shar",
    "social-date",
    "speechify-ignore",
    "speedbump",
    "sponsor",
    "springercitation",
    "sr-only",
    "_stats",
    "story-date",
    "story-navigation",
    "storyreadtime",
    "storysmall",
    "storypublishdate",
    "subject-label",
    "subhead",
    "submenu",
    "-subscribe-",
    "subscriber-drive",
    "subscription-",
    "_tags",
    "tags__item",
    "tag_list",
    "taxonomy",
    "table-of-contents",
    "tabs-",
    "terminaltout",
    "time-rubric",
    "timestamp",
    "time-read",
    "time-to-read",
    "tip_off",
    "tiptout",
    "-tout-",
    "toc-container",
    "toggle-caption",
    "tooltip-content",
    "topbar",
    "topic-authors",
    "topic-footer",
    "topic-list",
    "topic-subnav",
    "top-wrapper",
    "tree-item",
    "trending",
    "trust-feat",
    "trust-badge",
    "trust-project",
    "twitter",
    "u-hide",
    "upsell",
    "viewbottom",
    "yarpp-related",
    "visually-hidden",
    "welcomebox",
    "widget_pages",
]

# Pre-compiled regex for partial selector matching
PARTIAL_SELECTOR_REGEX: re.Pattern[str] = re.compile(
    "|".join(re.escape(p) for p in PARTIAL_SELECTOR_PATTERNS),
    re.IGNORECASE,
)

# Attributes to check for partial selector matches
TEST_ATTRIBUTES: tuple[str, ...] = (
    "class",
    "id",
    "data-test",
    "data-testid",
    "data-test-id",
    "data-qa",
    "data-cy",
)

# Navigation indicator patterns for scoring
NAVIGATION_INDICATORS: list[str] = [
    "advertisement",
    "all rights reserved",
    "banner",
    "cookie",
    "comments",
    "copyright",
    "follow me",
    "follow us",
    "footer",
    "header",
    "homepage",
    "login",
    "menu",
    "more articles",
    "more like this",
    "most read",
    "nav",
    "navigation",
    "newsletter",
    "popular",
    "privacy",
    "recommended",
    "register",
    "related",
    "responses",
    "share",
    "sidebar",
    "sign in",
    "sign up",
    "signup",
    "social",
    "sponsored",
    "subscribe",
    "terms",
    "trending",
]

# Non-content class patterns for scoring penalty
NON_CONTENT_CLASS_PATTERNS: list[str] = [
    "advert",
    "ad-",
    "ads",
    "banner",
    "cookie",
    "copyright",
    "footer",
    "header",
    "homepage",
    "menu",
    "nav",
    "newsletter",
    "popular",
    "privacy",
    "recommended",
    "related",
    "rights",
    "share",
    "sidebar",
    "social",
    "sponsored",
    "subscribe",
    "terms",
    "trending",
    "widget",
]

# Content protection selectors — elements whose presence indicates real content
CONTENT_PROTECTION_SELECTORS: list[str] = [
    "math",
    "[data-mathml]",
    ".katex",
    ".katex-mathml",
    ".katex-display",
    ".MathJax",
    ".MathJax_Display",
    ".MathJax_SVG",
    "mjx-container",
    "pre",
    "code",
    "table",
    "img",
    "picture",
    "video",
    "blockquote",
    "figure",
    'input[type="checkbox"]',  # task lists (GitHub-style)
]

# Elements that are allowed to be empty (void elements)
ALLOWED_EMPTY_ELEMENTS: frozenset[str] = frozenset(
    {
        "area",
        "audio",
        "base",
        "br",
        "col",
        "embed",
        "figure",
        "hr",
        "iframe",
        "img",
        "input",
        "link",
        "meta",
        "object",
        "param",
        "picture",
        "source",
        "svg",
        "td",
        "th",
        "track",
        "video",
        "wbr",
    }
)

# Content indicator tokens in class/id for isLikelyContent
CONTENT_INDICATOR_TOKENS: frozenset[str] = frozenset(
    {
        "article",
        "content",
        "entry",
        "image",
        "img",
        "font",
        "figure",
        "figcaption",
        "pre",
        "main",
        "post",
        "story",
        "table",
    }
)
