# -*- coding: utf-8 -*-
"""
========
itb_html
========
"""

__all__ = [
    'change_h_tags',
    'prettify_html',
]

from typing import Literal, Union, cast  # Union für ältere Python-Versionen

from bs4 import BeautifulSoup


def prettify_html(
    html: str
) -> str:
    """Prettify html (from bs4/BeautifulSoup)

    :param html: raw HTML string
    :return: prettified HTML string

    .. note:: This function is needed for Zope Python Scripts
        because even if bs4 can be imported, prettify throws
        an Unauthorized error in Restricted Python
    """
    soup = BeautifulSoup(html, 'html.parser')
    return cast(str, soup.prettify())  # Expliziter Cast zu str

def change_h_tags(
    html: str,
    change: int,
    returning: Literal['str', 'soup', 'pretty'] = 'str'
) -> Union[str, BeautifulSoup]:
    """Change all the H-tags in a HTML, increase or decrease by a certain number

    :param html: HTML string containing heading tags
    :param change: number of levels to shift (positive = increase, negative = decrease)
    :param returning: ``'str'`` (default), ``'soup'`` (BeautifulSoup object), or ``'pretty'``
    :return: modified HTML as string, prettified string, or BeautifulSoup object
    """
    if change == 0:
        if returning == 'soup':
            return BeautifulSoup(html, 'html.parser')
        return prettify_html(html) if returning == 'pretty' else html

    soup = BeautifulSoup(html, 'html.parser')

    # Collect all h-tags BEFORE modifying any (prevents double-shifting)
    collected = []
    for level in range(1, 7):
        new_level = max(1, min(6, level + change))
        for tag in soup.find_all(f'h{level}'):
            collected.append((tag, new_level))

    for tag, new_level in collected:
        tag.name = f'h{new_level}'

    if returning == 'soup':
        return soup
    elif returning == 'pretty':
        return soup.prettify()
    return str(soup)
