import re
from enum import Enum
from typing import Optional, Dict
import requests
from bs4 import BeautifulSoup

DEFAULT_HEADERS = {"User-Agent": "ietf-notebook/0.1.0"}


def get_mailing_list_name(wg_name: str) -> str:
    """
    Find the mailing list name from the WG 'about' page.
    """
    url = f"https://datatracker.ietf.org/wg/{wg_name}/about/"
    res = fetch_resource(url)
    if not res:
        return wg_name

    bs_soup = BeautifulSoup(res.text, "html.parser")

    # Strategy 1: Look for "List archive »" link
    archive_link = None
    for a_tag in bs_soup.find_all("a"):
        if "List archive" in a_tag.get_text():
            archive_link = a_tag
            break

    if archive_link:
        href_val = archive_link.get("href")
        if (
            isinstance(href_val, str)
            and "mailarchive.ietf.org/arch/browse/" in href_val
        ):
            parts = href_val.strip("/").split("/")
            return parts[-1]

    # Strategy 2: Look for "Address" row in mailing list table
    rows = bs_soup.find_all("tr")
    for row in rows:
        th = row.find("th")
        if th and "Address" in th.get_text():
            td = row.find("td")
            if td:
                email = td.get_text(strip=True)
                if "@" in email:
                    return str(email.split("@")[0])

    return wg_name


class Verbosity(Enum):
    """Logging verbosity settings."""

    QUIET = 0
    STATUS = 1
    VERBOSE = 2


class LogLevel(Enum):
    """Logging message levels."""

    ERROR = 0
    STATUS = 1
    PROGRESS = 2


def log(
    message: str,
    verbosity: Verbosity = Verbosity.STATUS,
    level: LogLevel = LogLevel.PROGRESS,
) -> None:
    """
    Print message based on verbosity level.
    - level: LogLevel.ERROR, LogLevel.STATUS, LogLevel.PROGRESS
    - verbosity: Verbosity.QUIET, Verbosity.STATUS, Verbosity.VERBOSE
    """
    if level == LogLevel.ERROR:
        print(f"[ERROR] {message}")
        return

    if verbosity == Verbosity.QUIET:
        return

    if verbosity == Verbosity.VERBOSE or (
        verbosity == Verbosity.STATUS and level == LogLevel.STATUS
    ):
        print(message)


def fetch_resource(
    url: str, headers: Optional[Dict[str, str]] = None
) -> Optional[requests.Response]:
    """Fetch a resource and return the response object."""
    combined_headers = DEFAULT_HEADERS.copy()
    if headers:
        combined_headers.update(headers)
    try:
        res = requests.get(url, headers=combined_headers, timeout=30)
        res.raise_for_status()
        return res
    except requests.RequestException as err:
        log(f"Error fetching {url}: {err}", level=LogLevel.ERROR)
        return None


def fetch_url(url: str, headers: Optional[Dict[str, str]] = None) -> Optional[str]:
    """Fetch content from a URL."""
    res = fetch_resource(url, headers=headers)
    return str(res.text) if res else None


def clean_html(html_content: str) -> str:
    """Simple HTML to text conversion using BeautifulSoup with aggressive cleaning."""
    if not html_content:
        return ""
    bs_soup = BeautifulSoup(html_content, "html.parser")

    # Remove common navigation and header/footer tags
    for element in bs_soup(["script", "style", "nav", "header", "footer", "aside"]):
        element.decompose()

    # Strip specific navigation and alert components
    for cls_name in ["navbar", "alert", "modal", "visually-hidden"]:

        def match_class(cls_val: Optional[str], target: str = cls_name) -> bool:
            return bool(
                cls_val and any(val.startswith(target) for val in cls_val.split())
            )

        for element in bs_soup.find_all(class_=match_class):
            if element.name not in ["body", "html", "main"]:
                element.decompose()

    # Specifically remove the "Skip to main content" links
    for skip_link in bs_soup.find_all("a"):
        skip_text = skip_link.get_text(strip=True).lower()
        if "skip to" in skip_text:
            skip_link.decompose()

    # Get text
    text = bs_soup.get_text()

    # Break into lines and remove leading and trailing space on each
    lines = (line.strip() for line in text.splitlines())

    # Prohibited patterns (mostly IETF boilerplate/footer links)
    prohibited = [
        r"^Privacy Statement$",
        r"^About IETF Datatracker$",
        r"^Version \d",
        r"^System Status$",
        r"^Report a bug$",
        r"^IETF LLC$",
        r"^IETF Trust$",
        r"^RFC Editor$",
        r"^IANA$",
        r"^NomComs$",
        r"^Downref registry$",
        r"^Liaison statements$",
    ]
    prohibited_regex = re.compile("|".join(prohibited), re.I)

    # Filter out lines that match prohibited patterns or are empty
    filtered_lines = []
    for line in lines:
        if not line:
            continue
        if prohibited_regex.match(line):
            continue
        filtered_lines.append(line)

    # Reassemble and drop blank lines
    text = "\n".join(filtered_lines)

    return text.strip()


def format_filename(name: str) -> str:
    """Format a string to be a safe filename."""
    return re.sub(r"[^\w\s-]", "", name).strip().lower().replace(" ", "_")
