import io
import PyPDF2
import docx
import logging
from typing import Union

logger = logging.getLogger(__name__)

def extract_text_from_pdf(file_content: bytes) -> str:
    """
    Extracts text from a PDF file with error handling.
    """
    try:
        pdf_reader = PyPDF2.PdfReader(io.BytesIO(file_content))
        text = ""
        for i, page in enumerate(pdf_reader.pages):
            try:
                page_text = page.extract_text()
                if page_text:
                    text += page_text + "\n"
                else:
                    logger.warning(f"No text extracted from PDF page {i}.")
            except Exception as page_err:
                logger.error(f"Error extracting text from PDF page {i}: {page_err}", exc_info=True)
        return text
    except Exception as e:
        logger.error(f"Failed to parse PDF file: {e}", exc_info=True)
        raise ValueError(f"Invalid PDF format or corrupted file: {e}")

def extract_text_from_docx(file_content: bytes) -> str:
    """
    Extracts text from a DOCX file with error handling.
    """
    try:
        doc = docx.Document(io.BytesIO(file_content))
        text = ""
        for para in doc.paragraphs:
            text += para.text + "\n"
        return text
    except Exception as e:
        logger.error(f"Failed to parse DOCX file: {e}", exc_info=True)
        raise ValueError(f"Invalid DOCX format or corrupted file: {e}")

def extract_text_from_bytes(file_content: bytes, filename: str) -> str:
    """
    Dispatcher for content extraction based on file extension.
    """
    logger.info(f"Extracting content from: {filename}")
    ext = filename.lower().split('.')[-1]
    
    if ext == 'pdf':
        return extract_text_from_pdf(file_content)
    elif ext == 'docx':
        return extract_text_from_docx(file_content)
    elif ext in ['txt', 'md', 'json', 'csv']:
        try:
            return file_content.decode('utf-8')
        except UnicodeDecodeError:
            logger.warning(f"UTF-8 decode failed for {filename}, trying latin-1...")
            try:
                return file_content.decode('latin-1', errors='ignore')
            except Exception as e:
                logger.error(f"Failed to decode text file {filename}: {e}", exc_info=True)
                raise ValueError(f"Unsupported encoding for text file: {filename}")
    else:
        logger.error(f"Unsupported file extension: {ext} for file {filename}")
        raise ValueError(f"Unsupported file format: {ext}. Supported types: PDF, DOCX, TXT, MD, JSON, CSV.")
