"""Answer normalization: duplicate headers, first lines, theses, lists, paragraphs."""

from __future__ import annotations

import re
from typing import Iterable

_HEADER_RE = re.compile(r"^(#{1,6})\s+(.+?)\s*$", re.MULTILINE)
_BOLD_HEADER_RE = re.compile(r"^\*\*(.+?)\*\*\s*$", re.MULTILINE)
_LIST_ITEM_RE = re.compile(r"^(\s*[-*•]|\s*\d+[.)])\s+(.+)$", re.MULTILINE)


def _normalize_key(value: str) -> str:
    text = str(value or "").strip().lower()
    text = re.sub(r"[^\w\sа-яё0-9]", " ", text, flags=re.IGNORECASE)
    return re.sub(r"\s+", " ", text).strip()


def _split_paragraphs(text: str) -> list[str]:
    parts = [part.strip() for part in re.split(r"\n{2,}", str(text or "")) if part.strip()]
    return parts


def _join_paragraphs(parts: Iterable[str]) -> str:
    return "\n\n".join(part.strip() for part in parts if str(part or "").strip()).strip()


def remove_duplicate_headers(text: str) -> str:
    value = str(text or "")
    if not value.strip():
        return ""

    seen: set[str] = set()
    lines: list[str] = []
    for line in value.splitlines():
        header_match = _HEADER_RE.match(line)
        bold_match = _BOLD_HEADER_RE.match(line) if not header_match else None
        title = ""
        if header_match:
            title = header_match.group(2)
        elif bold_match:
            title = bold_match.group(1)
        if title:
            key = _normalize_key(title)
            if key and key in seen:
                continue
            if key:
                seen.add(key)
        lines.append(line)
    return "\n".join(lines).strip()


def remove_duplicate_first_sentence(text: str) -> str:
    value = str(text or "").strip()
    if not value:
        return ""

    paragraphs = _split_paragraphs(value)
    if len(paragraphs) < 2:
        return value

    first_para = paragraphs[0]
    first_sentence_match = re.match(r"^(.+?[.!?])(?:\s+|$)", first_para, flags=re.DOTALL)
    first_sentence = (first_sentence_match.group(1) if first_sentence_match else first_para).strip()
    first_key = _normalize_key(first_sentence)
    if not first_key or len(first_key) < 24:
        return value

    filtered = [paragraphs[0]]
    for paragraph in paragraphs[1:]:
        para_key = _normalize_key(paragraph)
        if para_key == first_key:
            continue
        if para_key.startswith(first_key) or first_key.startswith(para_key):
            if abs(len(para_key) - len(first_key)) <= max(12, len(first_key) // 4):
                continue
        filtered.append(paragraph)
    return _join_paragraphs(filtered)


def remove_repeated_theses(text: str) -> str:
    paragraphs = _split_paragraphs(text)
    if len(paragraphs) < 2:
        return str(text or "").strip()

    seen: set[str] = set()
    kept: list[str] = []
    for paragraph in paragraphs:
        key = _normalize_key(paragraph)
        if not key:
            continue
        if key in seen:
            continue
        duplicate = False
        for prior in seen:
            if len(key) >= 40 and len(prior) >= 40:
                shorter, longer = (key, prior) if len(key) < len(prior) else (prior, key)
                if shorter in longer and len(shorter) / max(len(longer), 1) >= 0.72:
                    duplicate = True
                    break
        if duplicate:
            continue
        seen.add(key)
        kept.append(paragraph)
    return _join_paragraphs(kept)


def normalize_lists_and_paragraphs(text: str) -> str:
    value = str(text or "").strip()
    if not value:
        return ""

    value = re.sub(r"\n{3,}", "\n\n", value)
    value = re.sub(r"[ \t]+\n", "\n", value)
    value = re.sub(r"\n[ \t]+", "\n", value)

    list_seen: set[str] = set()
    normalized_lines: list[str] = []
    for line in value.splitlines():
        list_match = _LIST_ITEM_RE.match(line)
        if list_match:
            item_key = _normalize_key(list_match.group(2))
            if item_key and item_key in list_seen:
                continue
            if item_key:
                list_seen.add(item_key)
        normalized_lines.append(line.rstrip())

    collapsed = "\n".join(normalized_lines)
    collapsed = re.sub(r"(\n[-*•]\s+.+\n)(?:\1)+", r"\1", collapsed)
    return collapsed.strip()


def normalize_answer(text: str) -> str:
    value = str(text or "").strip()
    if not value:
        return ""
    for step in (
        remove_duplicate_headers,
        remove_duplicate_first_sentence,
        remove_repeated_theses,
        normalize_lists_and_paragraphs,
    ):
        value = step(value)
    return value.strip()
