from typing import Dict, List, Optional, Set
from bs4 import BeautifulSoup
from urllib.parse import urlparse, urljoin

from ._anchor_text import _anchor_text
from bp.browse.services.slugs import product_slug_from_href
from .APP_ROOT_PLACEHOLDER import APP_ROOT_PLACEHOLDER

def _rewrite_links_fragment(
    html: Optional[str],
    base_url: str,
    known_slugs: Set[str],
    category_allow_values: Set[str],
    valid_subs_by_top: Dict[str, Set[str]],
    current_product_slug: str,
    link_errors: List[Dict],
    link_externals: List[Dict],
    unknown_sub_paths: Set[str],
) -> str:
    if not html:
        return ""
    soup = BeautifulSoup(html, "lxml")
    base_host = urlparse(base_url).netloc

    for a in soup.find_all("a", href=True):
        raw = (a.get("href") or "").strip()
        if not raw:
            continue
        low = raw.lower()
        if low.startswith(("mailto:", "tel:", "javascript:", "data:")) or low.startswith("#"):
            continue
        abs_href = urljoin(base_url, raw)
        p = urlparse(abs_href)
        if not p.scheme or not p.netloc:
            continue
        if p.netloc != base_host:
            link_externals.append({
                "product": current_product_slug,
                "href": abs_href,
                "text": _anchor_text(a),
                "host": p.netloc,
            })
            continue
        parts = [x for x in (p.path or "").split("/") if x]
        if not parts:
            continue
        last = parts[-1].lower()
        if last.endswith((".html", ".htm")):
            target_slug = product_slug_from_href(abs_href)
            if target_slug and target_slug in known_slugs:
                a["href"] = f"{APP_ROOT_PLACEHOLDER}/product/{target_slug}"
            else:
                link_errors.append({
                    "product": current_product_slug,
                    "href": abs_href,
                    "text": _anchor_text(a),
                    "top": None,
                    "sub": None,
                    "target_slug": target_slug or None,
                    "type": "suma_product_unknown",
                })
            continue
        top = parts[0].lower()
        if top in category_allow_values:
            if len(parts) == 1:
                a["href"] = f"{APP_ROOT_PLACEHOLDER}/{top}"
            else:
                sub = parts[1]
                if sub.lower().endswith((".html", ".htm")):
                    sub = sub.rsplit(".", 1)[0]
                if sub in (valid_subs_by_top.get(top) or set()):
                    a["href"] = f"{APP_ROOT_PLACEHOLDER}/{top}/{sub}"
                else:
                    unknown_path = f"/{top}/{sub}"
                    unknown_sub_paths.add(unknown_path)
                    a["href"] = f"{APP_ROOT_PLACEHOLDER}{unknown_path}"
                    link_errors.append({
                        "product": current_product_slug,
                        "href": abs_href,
                        "text": _anchor_text(a),
                        "top": top,
                        "sub": sub,
                        "target_slug": None,
                        "type": "suma_category_invalid_sub_pending",
                    })
        else:
            link_errors.append({
                "product": current_product_slug,
                "href": abs_href,
                "text": _anchor_text(a),
                "top": top,
                "sub": parts[1] if len(parts) > 1 else None,
                "target_slug": None,
                "type": "suma_other",
            })

    for t in soup.find_all(["html", "body"]):
        t.unwrap()
    return "".join(str(c) for c in soup.contents).strip()

