from pathlib import Path

from pygeai import logger
from pygeai.core.base.clients import BaseClient
from pygeai.core.omni.endpoints import OMNI_PARSER_PROCESS
from pygeai.core.utils.validators import validate_status_code
from pygeai.core.utils.parsers import parse_json_response


class OmniParserClient(BaseClient):

    def process_file(
        self,
        file_path: str,
        start_page: int = None,
        end_page: int = None,
        hi_res_mode: bool = None,
        structure: str = None,
        dialogue: bool = None,
        output_format: str = None,
        password: str = None,
        cache: bool = False
    ) -> dict:
        """
        Processes a file and returns a textual representation using the OmniParser API.

        This method supports various file formats including PDF, DOCX, PPTX, XLSX, audio, and video files.
        It uploads the file to the OmniParser endpoint and returns structured text extraction results.

        :param file_path: str - Path to the file to be processed.
        :param start_page: int, optional - First page number to begin processing from (1-based).
        :param end_page: int, optional - Last page number to process (inclusive). Use 0 to mean until the end.
        :param hi_res_mode: bool, optional - Request high-resolution OCR/vision mode for complex scans.
        :param structure: str, optional - Set to "table" for spreadsheet/CSV-like sources when structured form is needed.
        :param dialogue: bool, optional - For audio/video: True to transcribe spoken dialogue, False for visual descriptions.
        :param output_format: str, optional - Preferred output text format: "plainText" (default), "html", or "markdown".
        :param password: str, optional - Password for password-protected files.
        :param cache: bool, optional - Whether to enable caching for the request. Defaults to False.

        :return: dict - A dictionary containing the processing results with status, parts, request_id, and usage.
        :raises FileNotFoundError: If the specified file does not exist.
        :raises ValueError: If validation fails for input parameters.
        """
        file_path_obj = Path(file_path)
        if not file_path_obj.is_file():
            raise FileNotFoundError(f"File not found: {file_path}")

        if start_page is not None and start_page < 0:
            raise ValueError("start_page must be a non-negative integer")

        if end_page is not None and end_page < 0:
            raise ValueError("end_page must be a non-negative integer")

        if start_page is not None and end_page is not None and start_page > end_page and end_page != 0:
            raise ValueError("start_page cannot be greater than end_page")

        data = {}
        if start_page is not None:
            data["startPage"] = str(start_page)

        if end_page is not None:
            data["endPage"] = str(end_page)

        if hi_res_mode is not None:
            data["hiResMode"] = str(hi_res_mode).lower()

        if structure is not None:
            data["structure"] = structure

        if dialogue is not None:
            data["dialogue"] = str(dialogue).lower()

        if output_format is not None:
            data["outputFormat"] = output_format

        if password is not None:
            data["password"] = password

        files = {"file": file_path_obj.open("rb")}

        logger.debug(f"Processing file {file_path} with OmniParser")

        headers = {}
        if cache:
            headers['X-Saia-Cache-Enabled'] = "true"

        try:
            response = self.api_service.post_files_multipart(
                endpoint=OMNI_PARSER_PROCESS,
                files=files,
                data=data,
                headers=headers
            )
            validate_status_code(response)
            return parse_json_response(response, "process file with omni-parser", file_path=file_path)

        finally:
            files["file"].close()
