import base64
import urllib.parse
import fitz  # PyMuPDF
from pdfminer.high_level import extract_text
from pdf2image import convert_from_path
import pytesseract
import chardet
import logging

class PdfExtractor:
    def __init__(self):
        self.logger = logging.getLogger(__name__)

    def extract_text(self, encoded_path):
        try:
            # Decode the base64 encoded path
            pdf_path = base64.b64decode(urllib.parse.unquote(encoded_path)).decode("utf-8")
            self.logger.info(f"Extracting text from PDF: {pdf_path}")

            extracted_text = ""
            
            # Try PyMuPDF first
            try:
                doc = fitz.open(pdf_path)
                for page in doc:
                    extracted_text += page.get_text("text")
                doc.close()
                
                if extracted_text.strip():
                    return self._detect_encoding(extracted_text)
                self.logger.info("No text found with PyMuPDF, trying PDFMiner...")
            except Exception as e:
                self.logger.error(f"PyMuPDF extraction failed: {str(e)}")

            # Try PDFMiner next
            try:
                extracted_text = extract_text(pdf_path)
                if extracted_text.strip():
                    return self._detect_encoding(extracted_text)
                self.logger.info("No text found with PDFMiner, trying OCR...")
            except Exception as e:
                self.logger.error(f"PDFMiner extraction failed: {str(e)}")

            # Finally try OCR
            try:
                images = convert_from_path(pdf_path)
                for img in images:
                    extracted_text += pytesseract.image_to_string(img, lang="eng")
                return self._detect_encoding(extracted_text)
            except Exception as e:
                self.logger.error(f"OCR extraction failed: {str(e)}")
                
            if not extracted_text.strip():
                raise ValueError("No text could be extracted from the PDF")
                
            return extracted_text

        except Exception as e:
            self.logger.error(f"PDF extraction failed: {str(e)}")
            raise

    def _detect_encoding(self, text):
        """Detect encoding and convert text to UTF-8."""
        try:
            result = chardet.detect(text.encode())
            encoding = result['encoding']
            if encoding:
                return text.encode(encoding).decode('utf-8', errors='ignore')
            return text
        except Exception as e:
            self.logger.error(f"Encoding detection failed: {str(e)}")
            return text