"""
PDF Text Extraction with Native + OCR Fallback
Phase 3 - Python Processing
"""

import sys
from pathlib import Path

# Add parent to path
sys.path.append(str(Path(__file__).parent.parent))

try:
    import PyPDF2
except ImportError:
    print("Installing PyPDF2...")
    import subprocess
    subprocess.check_call([sys.executable, "-m", "pip", "install", "PyPDF2"])
    import PyPDF2

try:
    import pdfplumber
except ImportError:
    print("Installing pdfplumber...")
    import subprocess
    subprocess.check_call([sys.executable, "-m", "pip", "install", "pdfplumber"])
    import pdfplumber

from pdf2image import convert_from_path
import pytesseract
from PIL import Image
import os

class PDFTextExtractor:
    """Extract text from PDF with OCR fallback"""
    
    def __init__(self, tesseract_path=None):
        if tesseract_path:
            pytesseract.pytesseract.tesseract_cmd = tesseract_path
    
    def extract_text_from_pdf(self, pdf_path):
        """
        Extract text from PDF page by page
        Returns: List of dicts with page info
        """
        pages = []
        
        try:
            # Method 1: Try pdfplumber (better for formatted text)
            pages = self._extract_with_pdfplumber(pdf_path)
            
            # Check if we got enough text
            total_text = ' '.join([p.get('text', '') for p in pages])
            
            if len(total_text.strip()) < 100:
                # Method 2: Try PyPDF2
                pages = self._extract_with_pypdf2(pdf_path)
                total_text = ' '.join([p.get('text', '') for p in pages])
            
            # For pages with no text, use OCR
            pages = self._apply_ocr_fallback(pdf_path, pages)
            
            return pages
            
        except Exception as e:
            print(f"Error extracting text: {e}")
            # Full OCR fallback
            return self._extract_full_ocr(pdf_path)
    
    def _extract_with_pdfplumber(self, pdf_path):
        """Extract text using pdfplumber"""
        pages = []
        
        try:
            with pdfplumber.open(pdf_path) as pdf:
                for i, page in enumerate(pdf.pages):
                    text = page.extract_text() or ''
                    
                    pages.append({
                        'page': i + 1,
                        'method': 'native_text' if len(text.strip()) > 50 else 'ocr',
                        'text': text.strip(),
                        'confidence': 1.0 if len(text.strip()) > 50 else 0.5
                    })
        except Exception as e:
            print(f"pdfplumber extraction failed: {e}")
            
        return pages
    
    def _extract_with_pypdf2(self, pdf_path):
        """Extract text using PyPDF2"""
        pages = []
        
        try:
            with open(pdf_path, 'rb') as file:
                reader = PyPDF2.PdfReader(file)
                
                for i in range(len(reader.pages)):
                    page = reader.pages[i]
                    text = page.extract_text() or ''
                    
                    pages.append({
                        'page': i + 1,
                        'method': 'native_text' if len(text.strip()) > 50 else 'ocr',
                        'text': text.strip(),
                        'confidence': 1.0 if len(text.strip()) > 50 else 0.5
                    })
        except Exception as e:
            print(f"PyPDF2 extraction failed: {e}")
            
        return pages
    
    def _apply_ocr_fallback(self, pdf_path, pages):
        """Apply OCR to pages with insufficient text"""
        try:
            # Convert PDF to images
            images = convert_from_path(pdf_path, dpi=300)
            
            for i, image in enumerate(images):
                if i < len(pages):
                    # Check if page needs OCR
                    if len(pages[i].get('text', '').strip()) < 50:
                        ocr_text = self._perform_ocr(image)
                        if ocr_text:
                            pages[i]['text'] = ocr_text
                            pages[i]['method'] = 'ocr'
                            pages[i]['confidence'] = 0.7
                else:
                    # Extra page not in original extraction
                    ocr_text = self._perform_ocr(image)
                    pages.append({
                        'page': i + 1,
                        'method': 'ocr',
                        'text': ocr_text,
                        'confidence': 0.7
                    })
        except Exception as e:
            print(f"OCR fallback error: {e}")
            
        return pages
    
    def _extract_full_ocr(self, pdf_path):
        """Full OCR extraction for scanned PDFs"""
        pages = []
        
        try:
            images = convert_from_path(pdf_path, dpi=300)
            
            for i, image in enumerate(images):
                text = self._perform_ocr(image)
                
                pages.append({
                    'page': i + 1,
                    'method': 'ocr',
                    'text': text,
                    'confidence': 0.7
                })
        except Exception as e:
            print(f"Full OCR extraction failed: {e}")
            
        return pages
    
    def _perform_ocr(self, image):
        """Perform OCR on an image"""
        try:
            # Preprocess image
            gray = image.convert('L')  # Convert to grayscale
            
            # Perform OCR
            text = pytesseract.image_to_string(gray, lang='eng')
            return text.strip()
        except Exception as e:
            print(f"OCR error: {e}")
            return ''
    
    def get_page_text(self, pdf_path):
        """Get formatted page-numbered text"""
        pages = self.extract_text_from_pdf(pdf_path)
        
        formatted_text = []
        for page in pages:
            formatted_text.append(f"\n{'='*60}")
            formatted_text.append(f"PAGE {page['page']} | Method: {page['method']}")
            formatted_text.append(f"{'='*60}\n")
            formatted_text.append(page['text'])
            formatted_text.append("\n")
        
        return '\n'.join(formatted_text), pages

# Test function
if __name__ == '__main__':
    import sys
    
    if len(sys.argv) > 1:
        pdf_path = sys.argv[1]
        extractor = PDFTextExtractor()
        formatted_text, pages = extractor.get_page_text(pdf_path)
        
        print(f"Extracted {len(pages)} pages")
        for page in pages:
            print(f"Page {page['page']}: {page['method']} ({len(page['text'])} chars)")