from __future__ import annotations

import html
import re
from pathlib import Path
from typing import Any

from PySide6.QtGui import QFontMetrics
from PySide6.QtWidgets import QToolTip



def parse_float(value: Any) -> float | None:
    if value is None:
        return None
    if isinstance(value, (int, float)):
        return float(value)
    if isinstance(value, str):
        s = value.strip()
        if not s:
            return None
        s = s.replace(",", ".")
        s = re.sub(r"[^0-9.\-+eE]", "", s)
        try:
            return float(s)
        except Exception:
            return None
    return None


def output_base_for_pdf(pdf: Path, input_root: Path | None) -> Path:
    if input_root is not None:
        try:
            rel = pdf.relative_to(input_root).with_suffix("")
            return Path(*rel.parts)
        except Exception:
            pass

    return Path(pdf.stem)


def friendly_exception_text(e: Exception) -> str:
    name = e.__class__.__name__
    msg = str(e).strip()

    if isinstance(e, FileNotFoundError):
        return "File not found."
    if isinstance(e, PermissionError):
        return "Insufficient permissions (cannot read/write)."

    if name in {"FileDataError", "EmptyFileError", "FzErrorFormat"}:
        return "The PDF is damaged or in an unsupported format."

    if not msg:
        return name

    if len(msg) > 200:
        msg = msg[:200].rstrip() + "…"

    return f"{name}: {msg}"


def tooltip_html(text: str, max_width_px: int = 720) -> str:
    t = (text or "").strip()
    if not t:
        return ""

    lines = t.splitlines() or [t]
    is_multiline = len(lines) > 1

    try:
        fm = QFontMetrics(QToolTip.font())
        text_px = max(fm.horizontalAdvance(line) for line in lines)
    except Exception:
        text_px = max(len(line) for line in lines) * 9

    if (not is_multiline) and text_px <= max_width_px:
        safe_nbsp = html.escape(t).replace(" ", "&nbsp;")
        width_px = min(max_width_px, max(1, text_px + 1))
        return (
            "<qt>"
            f"<table width='{width_px}' cellpadding='0' cellspacing='0'>"
            "<tr>"
            f"<td><nobr>{safe_nbsp}</nobr></td>"
            "</tr>"
            "</table>"
            "</qt>"
        )

    wrapped = t.replace(",", ",\u200b").replace(";", ";\u200b").replace("|", "|\u200b")
    if not re.search(r"\s", wrapped) and len(wrapped) > 30:
        wrapped = "\u200b".join(wrapped[i:i + 20] for i in range(0, len(wrapped), 20))

    safe_wrapped = html.escape(wrapped).replace("\n", "<br>")

    return (
        "<qt>"
        f"<table width='{max_width_px}' cellpadding='0' cellspacing='0'>"
        "<tr>"
        f"<td style='white-space:normal; padding:2px 2px 2px 2px;'>{safe_wrapped}</td>"
        "</tr>"
        "</table>"
        "</qt>"
    )