from __future__ import annotations

import re
import unicodedata
from dataclasses import dataclass
from html.parser import HTMLParser
from typing import Any


def _normalize_whitespace(value: Any) -> str:
    return re.sub(r"\s+", " ", str(value or "")).strip()


def _normalize_ascii(value: Any) -> str:
    text = unicodedata.normalize("NFKD", str(value or ""))
    return "".join(char for char in text if not unicodedata.combining(char))


def _normalize_label(value: Any) -> str:
    normalized = _normalize_ascii(_normalize_whitespace(value)).lower()
    normalized = re.sub(r"[^a-z0-9\s]+", " ", normalized)
    return _normalize_whitespace(normalized)


@dataclass(frozen=True)
class DiagnosticAidsHTMLBlock:
    kind: str
    payload: Any


class _DiagnosticAidsHTMLParser(HTMLParser):
    def __init__(self) -> None:
        super().__init__(convert_charrefs=True)
        self.blocks: list[DiagnosticAidsHTMLBlock] = []
        self._in_p = False
        self._p_buffer: list[str] = []

    def handle_starttag(self, tag: str, attrs: list[tuple[str, str | None]]) -> None:
        normalized = tag.lower()
        if normalized == "p":
            self._in_p = True
            self._p_buffer = []
        elif normalized == "br":
            self._append_text(" ")

    def handle_endtag(self, tag: str) -> None:
        if tag.lower() == "p" and self._in_p:
            text = _normalize_whitespace("".join(self._p_buffer))
            if text:
                self.blocks.append(DiagnosticAidsHTMLBlock("p", text))
            self._p_buffer = []
            self._in_p = False

    def handle_data(self, data: str) -> None:
        self._append_text(data)

    def _append_text(self, text: str) -> None:
        if self._in_p:
            self._p_buffer.append(text)


def _parse_blocks(html: str) -> list[DiagnosticAidsHTMLBlock]:
    parser = _DiagnosticAidsHTMLParser()
    parser.feed(str(html or ""))
    parser.close()
    return parser.blocks


def extract_html_paragraph_field(html: str, label: str) -> str:
    return extract_first_html_paragraph_field(html, (label,))


def extract_first_html_paragraph_field(html: str, labels: tuple[str, ...]) -> str:
    blocks = _parse_blocks(html)
    if not blocks:
        return ""

    normalized_labels = {_normalize_label(label) for label in labels}
    for index, block in enumerate(blocks):
        if block.kind != "p":
            continue
        if _normalize_label(block.payload) not in normalized_labels:
            continue
        for candidate in blocks[index + 1 :]:
            if candidate.kind == "p":
                return _normalize_whitespace(candidate.payload)
        return ""
    return ""
