# retoor <retoor@molodetz.nl>

import html
import json
import re
from datetime import datetime, timezone
from decimal import Decimal


def strip_html(text: str) -> str:
    if not text:
        return ""
    text = re.sub(r"<[^>]+>", " ", text)
    text = html.unescape(text)
    return re.sub(r"\s+", " ", text).strip()


_FLOAT_TOKEN = "@dpfloat@"


def plain_float(value: float) -> str:
    if value != value or value in (float("inf"), float("-inf")):
        return json.dumps(value)
    return format(Decimal(repr(value)), "f")


def _mark_floats(node):
    if isinstance(node, bool):
        return node
    if isinstance(node, float):
        return f"{_FLOAT_TOKEN}{plain_float(node)}{_FLOAT_TOKEN}"
    if isinstance(node, dict):
        return {key: _mark_floats(value) for key, value in node.items()}
    if isinstance(node, (list, tuple)):
        return [_mark_floats(item) for item in node]
    return node


def pretty_json(data, indent: int = 2) -> str:
    text = json.dumps(
        _mark_floats(data), indent=indent, ensure_ascii=False, default=str
    )
    return text.replace(f'"{_FLOAT_TOKEN}', "").replace(f'{_FLOAT_TOKEN}"', "")


def slugify(text: str) -> str:
    text = text.lower().strip()
    text = re.sub(r"[^a-z0-9-]", "-", text)
    text = re.sub(r"-+", "-", text)
    return text.strip("-")


def generate_uid() -> str:
    import uuid_utils

    return str(uuid_utils.uuid7())


def make_combined_slug(text: str, uid: str) -> str:
    short_uid = uid.replace("-", "")[-12:]
    slug_part = slugify(text)
    if not slug_part:
        return short_uid
    return f"{short_uid}-{slug_part}"


def time_ago(dt_str: str) -> str:
    dt = datetime.fromisoformat(dt_str)
    if dt.tzinfo is None:
        dt = dt.replace(tzinfo=timezone.utc)
    now = datetime.now(timezone.utc)
    diff = now - dt
    days = diff.days
    if days > 30:
        return dt.strftime("%d/%m/%Y")
    if days > 0:
        return f"{days}d ago"
    hours = diff.seconds // 3600
    if hours > 0:
        return f"{hours}h ago"
    minutes = diff.seconds // 60
    if minutes > 0:
        return f"{minutes}m ago"
    return "just now"


def extract_mentions(content: str) -> list[str]:
    if not content:
        return []
    return re.findall(r"(?:^|[\s(])@([a-zA-Z0-9_-]+)", content)


def format_date(dt_str: str, include_time: bool = False) -> str:
    if not dt_str:
        return ""
    try:
        dt = datetime.fromisoformat(dt_str)
        if include_time:
            return dt.strftime("%d/%m/%Y %H:%M")
        return dt.strftime("%d/%m/%Y")
    except (ValueError, TypeError):
        return dt_str
