<?php

namespace Limb_Chatbot\Includes\AI_Providers\Claude\Utilities;

use Limb_Chatbot\Includes\AI_Providers\Claude\Claude;
use Limb_Chatbot\Includes\AI_Providers\Claude\Endpoints\File\File_Endpoint;
use Limb_Chatbot\Includes\Data_Objects\Config;
use Limb_Chatbot\Includes\Data_Objects\File;
use Limb_Chatbot\Includes\Exceptions\Exception;
use Limb_Chatbot\Includes\Utilities\File_Utility as Global_Utility;

/**
 * Class File_Utility
 *
 * Utility class for managing file operations with the Claude AI provider.
 * Handles file upload, retrieval, and management via Claude's Files API.
 *
 * Claude Files API (Beta) supports:
 * - PDF documents (up to 32MB, 100 pages max)
 * - Images
 * - Text files
 *
 * @package Limb_Chatbot\Includes\AI_Providers\Claude\Utilities
 * @since 1.0.9
 */
class File_Utility {

	/**
	 * Default timeout for file operations.
	 *
	 * @var int
	 * @since 1.0.9
	 */
	const DEFAULT_TIMEOUT = 120;

	/**
	 * Configuration object related to this utility.
	 *
	 * @var Config|null
	 * @since 1.0.9
	 */
	public ?Config $config;

	/**
	 * Global file utility instance used for shared operations.
	 *
	 * @var Global_Utility
	 * @since 1.0.9
	 */
	public Global_Utility $global_utility;

	/**
	 * Endpoint instance to handle file API interactions.
	 *
	 * @var File_Endpoint
	 * @since 1.0.9
	 */
	public File_Endpoint $endpoint;

	/**
	 * Constructor.
	 *
	 * Initializes the file utility with the global utility, sets config if missing,
	 * and creates the file endpoint instance.
	 *
	 * @param  Global_Utility  $global_utility  Global file utility instance.
	 *
	 * @since 1.0.9
	 */
	public function __construct( Global_Utility $global_utility ) {
		$this->global_utility = $global_utility;
		if ( is_null( $this->global_utility->config ) ) {
			$this->config = Config::where( array( 'default' => true, 'related_to' => Claude::$id ) )->first();
		} else {
			$this->config = $this->global_utility->config;
		}
		$this->endpoint = new File_Endpoint( $this );
	}

	/**
	 * Returns the configuration object used by this utility.
	 *
	 * @return Config|null Configuration object or null if not set.
	 * @since 1.0.9
	 */
	public function get_config(): ?Config {
		return $this->config;
	}

	/**
	 * Get the timeout for file operations.
	 *
	 * @return int Timeout in seconds.
	 * @since 1.0.9
	 */
	public function get_timeout(): int {
		return self::DEFAULT_TIMEOUT;
	}

	/**
	 * Upload a file to Claude Files API.
	 *
	 * @param  File  $file  The File object to upload.
	 *
	 * @return array Array of metadata from the upload response.
	 * @throws Exception If upload fails.
	 * @since 1.0.9
	 */
	public function upload( File $file ): array {
		return $this->endpoint->upload( $file );
	}

	/**
	 * List files from Claude Files API.
	 *
	 * @param  int  $limit  Number of items to return.
	 * @param  string|null  $after_id  Cursor for pagination.
	 * @param  string|null  $before_id  Cursor for pagination.
	 *
	 * @return array List of file metadata.
	 * @throws Exception If request fails.
	 * @since 1.0.9
	 */
	public function list( int $limit = 20, ?string $after_id = null, ?string $before_id = null ): array {
		return $this->endpoint->list( $limit, $after_id, $before_id );
	}

	/**
	 * Retrieve file metadata.
	 *
	 * @param  string  $file_id  The file ID.
	 *
	 * @return array File metadata.
	 * @throws Exception If request fails.
	 * @since 1.0.9
	 */
	public function retrieve( string $file_id ): array {
		return $this->endpoint->retrieve( $file_id );
	}

	/**
	 * Download file content.
	 *
	 * @param  string  $file_id  The file ID.
	 *
	 * @return string Raw file content.
	 * @throws Exception If request fails.
	 * @since 1.0.9
	 */
	public function download( string $file_id ): string {
		return $this->endpoint->download( $file_id );
	}

	/**
	 * Delete a file.
	 *
	 * @param  string  $file_id  The file ID.
	 *
	 * @return array Deletion confirmation.
	 * @throws Exception If request fails.
	 * @since 1.0.9
	 */
	public function delete( string $file_id ): array {
		return $this->endpoint->delete( $file_id );
	}

	/**
	 * Refresh file metadata (check status).
	 *
	 * @param  File  $file  The file object to refresh.
	 *
	 * @return array Updated file metadata.
	 * @throws Exception If request fails.
	 * @since 1.0.9
	 */
	public function refresh( File $file ): array {
		return $this->endpoint->refresh( $file );
	}
}

