"""
Utility for handling OpenAI file uploads, particularly PDFs for GPT-4o vision models.
"""
import os
import time
from typing import Optional, Dict, Any, List
from pathlib import Path

import openai
from openai.types.file_object import FileObject
from tenacity import (
    retry,
    stop_after_attempt,
    wait_exponential,
    retry_if_exception_type
)

def upload_file(
    file_path: str,
    purpose: str = "assistants"
) -> FileObject:
    """
    Upload a file to OpenAI API.

    Args:
        file_path: Path to the file to upload
        purpose: Purpose of the file (default: 'assistants')

    Returns:
        FileObject: Response from OpenAI API
    """
    if not os.path.exists(file_path):
        raise FileNotFoundError(f"File not found: {file_path}")

    with open(file_path, "rb") as file:
        response = openai.files.create(
            file=file,
            purpose=purpose
        )

    return response

@retry(
    stop=stop_after_attempt(5),
    wait=wait_exponential(multiplier=1, min=2, max=60),
    retry=retry_if_exception_type(Exception)
)
def wait_for_file_processing(file_id: str, timeout: int = 300) -> FileObject:
    """
    Wait for a file to be processed by OpenAI API.

    Args:
        file_id: ID of the uploaded file
        timeout: Maximum time to wait in seconds

    Returns:
        FileObject: File object when processed
    """
    start_time = time.time()

    while True:
        try:
            file_obj = openai.files.retrieve(file_id)

            # If the file is processed, return it
            if file_obj.status == "processed":
                return file_obj

            # Check if we've exceeded the timeout
            if time.time() - start_time > timeout:
                raise TimeoutError(f"File processing timed out after {timeout} seconds")

            # Wait a bit before checking again
            time.sleep(5)
        except Exception as e:
            print(f"Error while waiting for file processing: {e}")
            raise

def delete_file(file_id: str) -> bool:
    """
    Delete a file from OpenAI API.

    Args:
        file_id: ID of the file to delete

    Returns:
        bool: True if deletion was successful
    """
    try:
        response = openai.files.delete(file_id)
        return response.deleted
    except Exception as e:
        print(f"Error deleting file {file_id}: {e}")
        return False

def list_files() -> List[FileObject]:
    """
    List all files uploaded to OpenAI API.

    Returns:
        List[FileObject]: List of file objects
    """
    return openai.files.list().data

def upload_pdf_for_vision(pdf_path: str) -> str:
    """
    Upload a PDF for use with GPT-4o vision models.

    Args:
        pdf_path: Path to the PDF file

    Returns:
        str: File ID of the uploaded PDF
    """
    print(f"Uploading PDF: {pdf_path}")
    file_obj = upload_file(pdf_path)
    file_id = file_obj.id

    print(f"PDF uploaded with ID: {file_id}")
    print("Waiting for file processing to complete...")

    # Wait for the file to be processed
    processed_file = wait_for_file_processing(file_id)
    print(f"File processing completed. Status: {processed_file.status}")

    return file_id