import logging
import mimetypes
import typing

logger = logging.getLogger(__name__)

mime_type_mapping = {
    "application/vnd.ms-powerpoint": "ppt",
    "application/vnd.openxmlformats-officedocument.presentationml.presentation": "pptx",
    "application/msword": "doc",
    "application/vnd.openxmlformats-officedocument.wordprocessingml.document": "docx",
    "application/vnd.ms-excel": "xls",
    "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": "xlsx",
    "application/pdf": "pdf",
    "text/csv": "csv",
    "application/csv": "csv",
    "application/json": "json",
    "text/json": "json",
    "text/plain": "txt",
    "text/tab-separated-values": "tsv",
    "application/tab-separated-values": "tsv",
}


def _get_extractor(file_type: str) -> typing.Callable:
    """Return the extractor function for a file type (lazy import)."""
    if file_type == "xlsx":
        from sharepoint2text.extractors.xlsx_extractor import read_xlsx

        return read_xlsx
    elif file_type == "xls":
        from sharepoint2text.extractors.xls_extractor import read_xls

        return read_xls
    elif file_type == "ppt":
        from sharepoint2text.extractors.ppt_extractor import read_ppt

        return read_ppt
    elif file_type == "pptx":
        from sharepoint2text.extractors.pptx_extractor import read_pptx

        return read_pptx
    elif file_type == "doc":
        from sharepoint2text.extractors.doc_extractor import read_doc

        return read_doc
    elif file_type == "docx":
        from sharepoint2text.extractors.docx_extractor import read_docx

        return read_docx
    elif file_type == "pdf":
        from sharepoint2text.extractors.pdf_extractor import read_pdf

        return read_pdf
    elif file_type in ("csv", "json", "txt", "tsv"):
        from sharepoint2text.extractors.plain_extractor import read_plain_text

        return read_plain_text
    else:
        raise RuntimeError(f"No extractor for file type: {file_type}")


def is_supported_file(path: str) -> bool:
    """Checks if the path is a supported file"""
    path = path.lower()
    mime_type, _ = mimetypes.guess_type(path)
    return mime_type in mime_type_mapping


def get_extractor(path: str) -> typing.Callable:
    """Analysis the path of a file and returns a suited extractor.
       The file MUST not exist (yet). The path or filename alone suffices to return an
       extractor.

    :returns a function of an extractor. All extractors take a file-like object as parameter
    :raises RuntimeError: File is not covered by any extractor
    """
    path = path.lower()

    mime_type, _ = mimetypes.guess_type(path)

    if mime_type in mime_type_mapping:
        file_type = mime_type_mapping[mime_type]
        logger.debug(
            f"Detected file type: {file_type} (MIME: {mime_type}) for file: {path}"
        )
        return _get_extractor(file_type)

    else:
        logger.debug(f"File [{path}] with mime type [{mime_type}] is not supported")
        raise RuntimeError(f"File type not supported: {mime_type}")
