"""Convert an EPUB file to markdown text."""

import re
import zipfile
from html import unescape
from html.parser import HTMLParser


def _remove_tags(html: str, tag: str) -> str:
    """Remove a tag and its content from HTML string."""
    pattern = re.compile(rf'<{tag}[^>]*>.*?</{tag}>', re.IGNORECASE | re.DOTALL)
    return pattern.sub('', html)


def _html_to_markdown(html: str) -> str:
    """Convert basic HTML to markdown.

    Handles headings, bold, italic, paragraphs, line breaks
    and strips remaining tags.

    Args:
        html: HTML string to convert.

    Returns:
        Markdown-formatted string.
    """
    # Remove script and style blocks
    text = _remove_tags(html, 'script')
    text = _remove_tags(text, 'style')

    # Headings h1-h6
    for level in range(6, 0, -1):
        hashes = '#' * level
        text = re.sub(
            rf'<h{level}[^>]*>(.*?)</h{level}>',
            lambda m, h=hashes: f'{h} {m.group(1).strip()}',
            text,
            flags=re.IGNORECASE | re.DOTALL,
        )

    # Bold
    text = re.sub(r'<strong[^>]*>(.*?)</strong>', r'**\1**', text, flags=re.IGNORECASE | re.DOTALL)
    text = re.sub(r'<b[^>]*>(.*?)</b>', r'**\1**', text, flags=re.IGNORECASE | re.DOTALL)

    # Italic
    text = re.sub(r'<em[^>]*>(.*?)</em>', r'*\1*', text, flags=re.IGNORECASE | re.DOTALL)
    text = re.sub(r'<i[^>]*>(.*?)</i>', r'*\1*', text, flags=re.IGNORECASE | re.DOTALL)

    # Paragraphs — append double newline after content
    text = re.sub(r'<p[^>]*>(.*?)</p>', lambda m: m.group(1).strip() + '\n\n', text, flags=re.IGNORECASE | re.DOTALL)

    # Line breaks
    text = re.sub(r'<br\s*/?>', '\n', text, flags=re.IGNORECASE)

    # Strip remaining HTML tags
    text = re.sub(r'<[^>]+>', '', text)

    # Unescape HTML entities
    text = unescape(text)

    # Normalize whitespace: collapse multiple blank lines into two
    text = re.sub(r'\n{3,}', '\n\n', text)
    text = re.sub(r'[ \t]+', ' ', text)

    return text.strip()


def _epub_via_ebooklib(epub_path: str) -> str:
    """Extract markdown from EPUB using ebooklib."""
    import ebooklib
    from ebooklib import epub

    book = epub.read_epub(epub_path)

    # Metadata
    title_meta = book.get_metadata('DC', 'title')
    author_meta = book.get_metadata('DC', 'creator')
    title = title_meta[0][0] if title_meta else 'Unknown Title'
    author = author_meta[0][0] if author_meta else 'Unknown Author'

    parts = [f'# {title}', f'**Author:** {author}']

    for item in book.get_items_of_type(ebooklib.ITEM_DOCUMENT):
        content = item.get_content().decode('utf-8', errors='replace')
        md = _html_to_markdown(content)
        if md:
            parts.append(md)

    return '\n\n'.join(parts)


def _epub_via_zipfile(epub_path: str) -> str:
    """Extract markdown from EPUB using zipfile (fallback)."""
    parts = []
    with zipfile.ZipFile(epub_path, 'r') as zf:
        html_files = sorted(
            name for name in zf.namelist()
            if name.lower().endswith(('.html', '.xhtml', '.htm'))
        )
        for name in html_files:
            raw = zf.read(name).decode('utf-8', errors='replace')
            md = _html_to_markdown(raw)
            if md:
                parts.append(md)

    return '\n\n'.join(parts)


def epub_to_markdown(epub_path: str) -> str:
    """Convert an EPUB ebook to markdown.

    Attempts to use ebooklib for structured extraction (title, author,
    document items). Falls back to manual ZIP extraction if ebooklib is
    not installed.

    Args:
        epub_path: Path to the .epub file.

    Returns:
        Markdown string with the book content.

    Raises:
        Exception: If the file cannot be read or is not a valid EPUB.
    """
    try:
        return _epub_via_ebooklib(epub_path)
    except ImportError:
        return _epub_via_zipfile(epub_path)
