"""
PDF Parsing module voor Elephate CLI

Bevat functies voor:
- PDF classificatie (PDF_TEXT vs TECH_DRAWING)
- Tekst extractie
- Directory scanning
"""

import os
import math
from enum import Enum
from pathlib import Path
from typing import List, Dict, Any, Optional, Tuple
from dataclasses import dataclass

from pypdf import PdfReader

# PyMuPDF is optioneel voor tile generatie
try:
    import fitz  # PyMuPDF
    PYMUPDF_AVAILABLE = True
except ImportError:
    PYMUPDF_AVAILABLE = False


class DocumentType(str, Enum):
    """Type document gebaseerd op inhoud en formaat"""
    PDF_TEXT = "pdf_text"           # Tekstdocumenten (bestekken, contracten)
    TECH_DRAWING = "tech_drawing"   # Technische tekeningen (bouwkundig/installatie)
    UNKNOWN = "unknown"             # Niet-geclassificeerd


@dataclass
class PDFInfo:
    """Informatie over een PDF bestand"""
    path: str
    filename: str
    doc_type: DocumentType
    num_pages: int
    total_text_length: int
    is_large_format: bool

    @property
    def avg_text_per_page(self) -> float:
        if self.num_pages == 0:
            return 0
        return self.total_text_length / self.num_pages


def classify_pdf(file_path: str) -> Tuple[DocumentType, PDFInfo]:
    """
    Classificeer een PDF als tekst-document of technische tekening.

    Heuristiek:
    1. Pagina-afmetingen > 1000 punten → TECH_DRAWING (A3+ formaat)
    2. Gemiddeld < 50 tekens per pagina → TECH_DRAWING (gescand/tekening)
    3. Anders → PDF_TEXT

    Returns:
        Tuple van (DocumentType, PDFInfo)
    """
    filename = os.path.basename(file_path)

    try:
        reader = PdfReader(file_path)

        is_large_format = False
        total_text_len = 0
        num_pages = len(reader.pages)

        if num_pages == 0:
            return DocumentType.UNKNOWN, PDFInfo(
                path=file_path,
                filename=filename,
                doc_type=DocumentType.UNKNOWN,
                num_pages=0,
                total_text_length=0,
                is_large_format=False
            )

        for page in reader.pages:
            try:
                width = float(page.mediabox.width)
                height = float(page.mediabox.height)

                # 1000 points is roughly 35cm / 13.8 inches. A3 is ~1190 pts height or width.
                if width > 1000 or height > 1000:
                    is_large_format = True
            except:
                pass  # Default to standard if mediabox is missing

            text = page.extract_text()
            if text:
                total_text_len += len(text)

        avg_text_per_page = total_text_len / num_pages if num_pages > 0 else 0

        # Heuristic classification
        if is_large_format:
            doc_type = DocumentType.TECH_DRAWING
        elif avg_text_per_page < 50:
            doc_type = DocumentType.TECH_DRAWING
        else:
            doc_type = DocumentType.PDF_TEXT

        return doc_type, PDFInfo(
            path=file_path,
            filename=filename,
            doc_type=doc_type,
            num_pages=num_pages,
            total_text_length=total_text_len,
            is_large_format=is_large_format
        )

    except Exception as e:
        return DocumentType.UNKNOWN, PDFInfo(
            path=file_path,
            filename=filename,
            doc_type=DocumentType.UNKNOWN,
            num_pages=0,
            total_text_length=0,
            is_large_format=False
        )


def extract_text_from_pdf(file_path: str) -> List[Dict[str, Any]]:
    """
    Extraheer tekst uit alle pagina's van een PDF.

    Returns:
        List van pagina's met tekst en metadata
    """
    try:
        reader = PdfReader(file_path)
        parsed_pages = []

        for i, page in enumerate(reader.pages):
            text = page.extract_text()
            if text:
                parsed_pages.append({
                    "page_number": i + 1,
                    "text_segment": text,
                    "char_count": len(text),
                    "metadata": {}
                })

        return parsed_pages

    except Exception as e:
        return []


def get_drawing_metadata(file_path: str) -> Dict[str, Any]:
    """
    Analyseer een technische tekening en geef metadata terug.

    Note: In de mockup worden geen tiles daadwerkelijk gegenereerd.
    Dit geeft alleen metadata over wat er zou worden gegenereerd.
    """
    if not PYMUPDF_AVAILABLE:
        # Fallback zonder PyMuPDF
        try:
            reader = PdfReader(file_path)
            return {
                "pages": [
                    {
                        "page_number": i + 1,
                        "estimated_tiles": 4,  # Geschat
                        "rows": 2,
                        "cols": 2
                    }
                    for i in range(len(reader.pages))
                ],
                "total_pages": len(reader.pages),
                "pymupdf_available": False
            }
        except:
            return {"error": "Could not read PDF", "pymupdf_available": False}

    try:
        doc = fitz.open(file_path)
        pages_data = []
        total_tiles = 0

        for i, page in enumerate(doc):
            tile_size = 512
            zoom = 2  # 144 DPI

            width_pts = page.rect.width
            height_pts = page.rect.height

            width_px = int(width_pts * zoom)
            height_px = int(height_pts * zoom)

            cols = math.ceil(width_px / tile_size)
            rows = math.ceil(height_px / tile_size)
            num_tiles = rows * cols
            total_tiles += num_tiles

            pages_data.append({
                "page_number": i + 1,
                "width_pts": width_pts,
                "height_pts": height_pts,
                "width_px": width_px,
                "height_px": height_px,
                "rows": rows,
                "cols": cols,
                "num_tiles": num_tiles
            })

        doc.close()

        return {
            "pages": pages_data,
            "total_pages": len(pages_data),
            "total_tiles": total_tiles,
            "pymupdf_available": True
        }

    except Exception as e:
        return {"error": str(e), "pymupdf_available": PYMUPDF_AVAILABLE}


def scan_directory(paths: List[str], recursive: bool = True) -> List[PDFInfo]:
    """
    Scan directories en bestanden voor PDFs en classificeer ze.

    Args:
        paths: List van paden (directories of bestanden)
        recursive: Zoek ook in subdirectories

    Returns:
        List van PDFInfo objecten
    """
    pdf_files: List[PDFInfo] = []

    for path in paths:
        path_obj = Path(path)

        if not path_obj.exists():
            continue

        if path_obj.is_file():
            if path_obj.suffix.lower() == '.pdf':
                _, pdf_info = classify_pdf(str(path_obj))
                pdf_files.append(pdf_info)

        elif path_obj.is_dir():
            pattern = '**/*.pdf' if recursive else '*.pdf'
            for pdf_path in path_obj.glob(pattern):
                _, pdf_info = classify_pdf(str(pdf_path))
                pdf_files.append(pdf_info)

    # Sorteer op bestandsnaam
    pdf_files.sort(key=lambda x: x.filename.lower())

    return pdf_files
