"""Convert a PDF file to markdown, with heading detection and table extraction."""

import os
import sys

import pdfplumber

# Allow import from same directory when run directly
_DIR = os.path.dirname(os.path.abspath(__file__))
if _DIR not in sys.path:
    sys.path.insert(0, _DIR)

from extract_pdf_bookmarks import extract_pdf_bookmarks
from detect_headings_by_font import detect_headings_by_font
from format_table_to_markdown import format_table_to_markdown


def pdf_to_markdown(
    pdf_path: str,
    heading_detection: str = "auto",
) -> tuple[str, dict]:
    """Convert a PDF file to markdown.

    Extracts text, tables, and injects detected headings from bookmarks or
    font size analysis.

    Args:
        pdf_path: Path to the PDF file.
        heading_detection: Strategy for detecting headings:
            - "bookmarks": use PDF outline/bookmarks only.
            - "font": analyze font size distribution.
            - "auto": try bookmarks first, fall back to font analysis.

    Returns:
        tuple[str, dict]: (markdown_content, metadata_dict).
            metadata_dict contains: {"pages": int, "heading_strategy": str,
            "headings_found": int, "tables_found": int}

    Raises:
        FileNotFoundError: If pdf_path does not exist.
        Exception: If the PDF cannot be opened or is corrupted.
    """
    if not os.path.exists(pdf_path):
        raise FileNotFoundError(f"PDF not found: {pdf_path}")

    with pdfplumber.open(pdf_path) as pdf:
        total_pages = len(pdf.pages)

        # Step 1: Detect headings
        headings: list[dict] = []
        strategy_used = heading_detection

        if heading_detection in ("bookmarks", "auto"):
            headings = extract_pdf_bookmarks(pdf)
            if headings:
                strategy_used = "bookmarks"
            elif heading_detection == "auto":
                headings = detect_headings_by_font(pdf)
                strategy_used = "font" if headings else "none"
        elif heading_detection == "font":
            headings = detect_headings_by_font(pdf)
            strategy_used = "font"

        # Step 2: Group headings by page number
        headings_by_page: dict[int, list[dict]] = {}
        for h in headings:
            pn = h.get("page_num")
            if pn is not None:
                headings_by_page.setdefault(pn, []).append(h)

        # Step 3: Build markdown page by page
        sections: list[str] = []
        tables_found = 0

        for page_idx, page in enumerate(pdf.pages):
            page_num = page_idx + 1
            page_parts: list[str] = []

            # Inject headings for this page
            for h in headings_by_page.get(page_num, []):
                level = h["level"]
                title = h["title"]
                page_parts.append(f"{'#' * level} {title}")

            # Extract page text
            text = page.extract_text() or ""
            if text.strip():
                page_parts.append(text.strip())

            # Extract tables
            try:
                tables = page.extract_tables()
            except Exception:
                tables = []

            for table in tables:
                if not table:
                    continue
                # Convert all cells to strings, treating None as empty
                str_table = [
                    [str(cell) if cell is not None else "" for cell in row]
                    for row in table
                ]
                md_table = format_table_to_markdown(str_table)
                if md_table:
                    page_parts.append(md_table)
                    tables_found += 1

            if page_parts:
                sections.append("\n\n".join(page_parts))

        markdown_content = "\n\n".join(sections)

        metadata = {
            "pages": total_pages,
            "heading_strategy": strategy_used,
            "headings_found": len(headings),
            "tables_found": tables_found,
        }

        return markdown_content, metadata
