"""
Document ingestion helpers: canonical PDF for Office files, page-wise text for indexing.
"""
from __future__ import annotations

import os
from typing import Callable, List, Optional, Tuple

from app.utils.content_extractor import ContentExtractor
from app.utils.document_preview import (
    DEFAULT_PREVIEW_PDF_CACHE_DIR,
    ensure_office_preview_pdf,
)
from app.utils.page_snapshot_mapping import join_page_texts

OFFICE_EXTENSIONS = frozenset({"doc", "docx"})


def preview_pdf_path(
    file_id: str,
    cache_dir: str = DEFAULT_PREVIEW_PDF_CACHE_DIR,
) -> str:
    """Persisted preview PDF path for *file_id* (Office docs; PDFs use source path)."""
    return os.path.join(cache_dir, f"{file_id}.pdf")


def canonical_pdf_path(
    source_path: str,
    file_id: str,
    file_ext: str,
    cache_dir: str = DEFAULT_PREVIEW_PDF_CACHE_DIR,
) -> str:
    """Return the PDF used for page text extraction and inline preview."""
    ext = (file_ext or "").lower().lstrip(".")
    if ext == "pdf":
        return source_path
    if ext in OFFICE_EXTENSIONS:
        return ensure_office_preview_pdf(source_path, file_id, cache_dir=cache_dir)
    return source_path


def extract_page_texts_for_path(
    source_path: str,
    file_ext: str,
    *,
    should_cancel: Optional[Callable[[], bool]] = None,
) -> List[str]:
    """Per-page text from source file (temporary Office conversion when needed)."""
    ext = (file_ext or "").lower().lstrip(".")
    if ext == "pdf":
        return ContentExtractor.extract_pdf_page_texts(
            source_path, should_cancel=should_cancel
        )
    if ext in OFFICE_EXTENSIONS:
        from app.utils.document_preview import convert_office_file_to_pdf

        pdf_path, cleanup_paths = convert_office_file_to_pdf(source_path)
        try:
            return ContentExtractor.extract_pdf_page_texts(pdf_path)
        finally:
            for path in cleanup_paths:
                try:
                    if path and os.path.isfile(path):
                        os.remove(path)
                    elif path and os.path.isdir(path):
                        import shutil

                        shutil.rmtree(path, ignore_errors=True)
                except OSError:
                    pass
    return []


def prepare_ingestion(
    source_path: str,
    file_id: str,
    file_ext: str,
    *,
    cache_dir: str = DEFAULT_PREVIEW_PDF_CACHE_DIR,
    should_cancel: Optional[Callable[[], bool]] = None,
) -> Tuple[str, List[str], str]:
    """
    Persist Office preview PDF when needed and extract page texts from canonical PDF.

    Returns (full_text, page_texts, canonical_pdf_path).
    """
    ext = (file_ext or "").lower().lstrip(".")
    if ext not in OFFICE_EXTENSIONS | {"pdf"}:
        return "", [], source_path

    if ext in OFFICE_EXTENSIONS:
        canonical_pdf_path(source_path, file_id, ext, cache_dir=cache_dir)

    pdf_path = canonical_pdf_path(source_path, file_id, ext, cache_dir=cache_dir)
    page_texts = ContentExtractor.extract_pdf_page_texts(
        pdf_path, should_cancel=should_cancel
    )
    full_text, _ = join_page_texts(page_texts)
    full_text = (full_text or "").strip()
    if not full_text:
        full_text = "No text extracted from document"
    return full_text, page_texts, pdf_path


def extract_indexing_texts(
    source_path: str,
    file_id: str,
    file_ext: str,
    *,
    cache_dir: str = DEFAULT_PREVIEW_PDF_CACHE_DIR,
    should_cancel: Optional[Callable[[], bool]] = None,
) -> Tuple[str, List[str], str]:
    """
    Extract full document text and per-page texts from the canonical PDF.

    Returns (full_text, page_texts, canonical_pdf_path).
    """
    ext = (file_ext or "").lower().lstrip(".")
    if ext in OFFICE_EXTENSIONS | {"pdf"}:
        return prepare_ingestion(
            source_path,
            file_id,
            ext,
            cache_dir=cache_dir,
            should_cancel=should_cancel,
        )

    return "", [], source_path
