# ============================================================================
# OCR FUNCTIONALITY DISABLED - USING LLAMAPARSE ONLY FOR ALL DOCUMENT TYPES
# ============================================================================
# LlamaParse handles both PDF and image files (JPEG, PNG, etc.)
# No need for separate OCR processing
# ============================================================================

# import easyocr  # DISABLED - Not using OCR anymore
import PyPDF2
from PIL import Image
import io
import re
import os
import numpy as np
from typing import Optional, Tuple
from fastapi import UploadFile


class FileProcessor:
    """Utility class for processing files and extracting text content
    
    NOTE: OCR functionality has been disabled. All document parsing is now
    handled exclusively by LlamaParse which supports both PDFs and images.
    """
    
    # # Initialize OCR reader as class variable to avoid reloading
    # _ocr_reader = None
    
    # @classmethod
    # def _get_ocr_reader(cls):
    #     """Get or create EasyOCR reader instance"""
    #     if cls._ocr_reader is None:
    #         try:
    #             # Initialize with English support, no GPU needed
    #             cls._ocr_reader = easyocr.Reader(['en'], gpu=False)
    #         except Exception as e:
    #             raise Exception(f"Failed to initialize OCR reader: {str(e)}")
    #     return cls._ocr_reader
    
    @staticmethod
    async def extract_text_from_file(file: UploadFile) -> str:
        """Extract text from uploaded file (image or PDF)
        
        DEPRECATED: This method is no longer used. All text extraction
        is now handled by LlamaParse via URL-based processing.
        """
        raise NotImplementedError(
            "Local file processing is deprecated. "
            "Use LlamaParse with document URLs instead."
        )
        
        # try:
        #     content = await file.read()
        #     
        #     if file.content_type.startswith('image/'):
        #         return FileProcessor._extract_text_from_image(content)
        #     elif file.content_type == 'application/pdf':
        #         return FileProcessor._extract_text_from_pdf(content)
        #     else:
        #         raise ValueError(f"Unsupported file type: {file.content_type}")
        #         
        # except Exception as e:
        #     raise Exception(f"Error processing file: {str(e)}")
    
    # @staticmethod
    # def _extract_text_from_image(image_content: bytes) -> str:
    #     """Extract text from image using EasyOCR (no external dependencies)"""
    #     # DISABLED - Using LlamaParse instead
    #     raise NotImplementedError("OCR disabled - use LlamaParse")
    #     
    #     # try:
    #     #     # Get OCR reader
    #     #     reader = FileProcessor._get_ocr_reader()
    #     #     
    #     #     # Convert bytes to numpy array
    #     #     image = Image.open(io.BytesIO(image_content))
    #     #     image_np = np.array(image)
    #     #     
    #     #     # Extract text using EasyOCR
    #     #     results = reader.readtext(image_np)
    #     #     
    #     #     # Combine all detected text
    #     #     extracted_text = []
    #     #     for (bbox, text, confidence) in results:
    #     #         if confidence > 0.5:  # Only include text with decent confidence
    #     #             extracted_text.append(text)
    #     #     
    #     #     return ' '.join(extracted_text).strip()
    #     #     
    #     # except Exception as e:
    #     #     raise Exception(f"Error extracting text from image: {str(e)}")
    
    @staticmethod
    def _extract_text_from_pdf(pdf_content: bytes) -> str:
        """Extract text from PDF file"""
        try:
            pdf_reader = PyPDF2.PdfReader(io.BytesIO(pdf_content))
            text = ""
            
            for page in pdf_reader.pages:
                text += page.extract_text() + "\n"
            
            return text.strip()
        except Exception as e:
            raise Exception(f"Error extracting text from PDF: {str(e)}")
    
    @staticmethod
    def extract_name_from_text(text: str) -> Optional[str]:
        """Extract name patterns from text"""
        # Simple name pattern matching - can be enhanced based on requirements
        name_patterns = [
            r'\b[A-Z][a-z]+ [A-Z][a-z]+\b',  # First Last
            r'\b[A-Z][a-z]+ [A-Z]\. [A-Z][a-z]+\b',  # First M. Last
            r'\b[A-Z][a-z]+ [A-Z][a-z]+ [A-Z][a-z]+\b'  # First Middle Last
        ]
        
        for pattern in name_patterns:
            matches = re.findall(pattern, text)
            if matches:
                return matches[0]  # Return first match
        
        return None
    
    @staticmethod
    def extract_address_from_text(text: str) -> Optional[str]:
        """Extract address patterns from text"""
        # Address pattern matching - can be enhanced based on requirements
        address_patterns = [
            r'\d+\s+[A-Za-z\s]+(?:Street|St|Avenue|Ave|Road|Rd|Lane|Ln|Drive|Dr|Boulevard|Blvd|Way|Place|Pl)',
            r'\d+\s+[A-Za-z\s]+,\s*[A-Za-z\s]+,\s*[A-Z]{2}\s+\d{5}',  # US format
            r'\d+\s+[A-Za-z\s]+\s+[A-Za-z\s]+\s+\d{4,6}'  # General format
        ]
        
        for pattern in address_patterns:
            matches = re.findall(pattern, text, re.IGNORECASE)
            if matches:
                return matches[0]  # Return first match
        
        return None
    
    @staticmethod
    def match_text_content(extracted_text: str, search_text: str, match_type: str) -> Tuple[bool, Optional[str]]:
        """Match extracted content with search text based on type"""
        if match_type == "name":
            extracted_name = FileProcessor.extract_name_from_text(extracted_text)
            if extracted_name and search_text.lower() in extracted_name.lower():
                return True, extracted_name
        elif match_type == "address":
            extracted_address = FileProcessor.extract_address_from_text(extracted_text)
            if extracted_address and search_text.lower() in extracted_address.lower():
                return True, extracted_address
        
        return False, None