<?php

namespace Limb_Chatbot\Includes\AI_Providers\Claude;

use Limb_Chatbot\Includes\AI_Providers\AI_Provider;
use Limb_Chatbot\Includes\Config_Dependent_Interface;
use Limb_Chatbot\Includes\Data_Objects\Config;
use Limb_Chatbot\Includes\Exceptions\Error_Codes;
use Limb_Chatbot\Includes\Exceptions\Exception;
use Limb_Chatbot\Includes\Interfaces\File_Upload_Capable_Interface;
use Limb_Chatbot\Includes\Utilities\AI_Model_Utility;

/**
 * Class Claude
 *
 * AI Provider implementation for Anthropic Claude.
 *
 * @package Limb_Chatbot\Includes\AI_Providers\Claude
 * @since 1.0.9
 */
class Claude extends AI_Provider implements Config_Dependent_Interface, File_Upload_Capable_Interface {

	/**
	 * Base URL for Claude API.
	 *
	 * @var string
	 * @since 1.0.9
	 */
	const API_BASE_URL = 'https://api.anthropic.com/';

	/**
	 * Claude API version.
	 *
	 * @var string
	 * @since 1.0.9
	 */
	const API_VERSION = '2023-06-01';

	/**
	 * Assistant role identifier for Claude.
	 *
	 * @var string
	 * @since 1.0.9
	 */
	const ROLE_ASSISTANT = 'assistant';

	/**
	 * User role identifier for Claude.
	 *
	 * @var string
	 * @since 1.0.9
	 */
	const ROLE_USER = 'user';

	/**
	 * Unique ID for Claude provider.
	 *
	 * @var string
	 * @since 1.0.9
	 */
	public static string $id = 'claude';

	/**
	 * Human-readable name for the provider.
	 *
	 * @var string
	 * @since 1.0.9
	 */
	public static string $name = 'Claude';

	/**
	 * Default timeout for Claude API requests, in seconds.
	 *
	 * @var int
	 * @since 1.0.9
	 */
	public static int $timeout = 120;

	/**
	 * Claude constructor.
	 *
	 * @since 1.0.9
	 */
	public function __construct() {
		// No hooks needed - Claude uses straightforward pricing.
	}

	/**
	 * Validates whether the given configuration contains valid API credentials for Claude.
	 *
	 * Validates by attempting to list available models from the Claude API.
	 * Handles Claude-specific error codes:
	 * - 400: invalid_request_error - Invalid request body format
	 * - 401: authentication_error - Wrong API key
	 * - 403: permission_error - No permission for resource
	 * - 429: rate_limit_error - Rate limit reached
	 * - 500: api_error - Server encounters an issue
	 * - 529: overloaded_error - Server overloaded
	 *
	 * @param  Config  $config  Configuration object to validate.
	 *
	 * @return bool True if valid API credentials; false otherwise.
	 * @throws Exception If authentication fails or other API errors occur.
	 * @since 1.0.9
	 *
	 */
	public function is_valid_config( Config $config ): bool {
		try {
			$models = ( new AI_Model_Utility( null, $config, $this->get_id() ) )->list();

			return ! empty( $models );
		} catch ( Exception $e ) {
			// Re-throw authentication errors with clear messages
			$error_code = $e->get_error_code();

			switch ( $error_code ) {
				case Error_Codes::AUTHENTICATION_UNAUTHORIZED:
				case Error_Codes::AUTHENTICATION_API_KEY_MISSING:
					throw new Exception(
						Error_Codes::AUTHENTICATION_UNAUTHORIZED,
						__( 'Claude API authentication failed. Please check your API key.', 'limb-chatbot' ),
						$e->get_error_data()
					);

				case Error_Codes::VALIDATION_INVALID_VALUE:
					throw new Exception(
						Error_Codes::VALIDATION_INVALID_VALUE,
						__( 'Claude API request contains invalid format or parameters.', 'limb-chatbot' ),
						$e->get_error_data()
					);

				case Error_Codes::TECHNICAL_ERROR:
					throw new Exception(
						Error_Codes::TECHNICAL_ERROR,
						__( 'Claude API server error. Please retry after a brief wait.', 'limb-chatbot' ),
						$e->get_error_data()
					);

				default:
					throw $e;
			}
		}
	}

	/**
	 * Checks if the given MIME type is supported for file uploads.
	 *
	 * Claude supports:
	 * - Images: JPEG, PNG, GIF, WebP
	 * - Documents: PDF, plain text
	 *
	 * @param  string  $mime_type  The MIME type to check.
	 * @param  string|null  $purpose  The purpose of the file (optional).
	 *
	 * @return bool True if MIME type is supported.
	 * @since 1.0.9
	 */
	public function supports_mime_type( string $mime_type, ?string $purpose = null ): bool {
		$supported_mime_types = array(
			// Images
			'image/jpeg',
			'image/png',
			'image/gif',
			'image/webp',
			// Documents
			'application/pdf',
			'text/plain',
		);

		return in_array( $mime_type, $supported_mime_types, true );
	}

	/**
	 * Returns the default embedding model for Claude.
	 *
	 * Note: Claude does not provide embeddings - use Voyage AI for embeddings.
	 *
	 * @return null Claude does not support embeddings.
	 * @since 1.0.9
	 */
	public function get_default_embedding_model() {
		// Claude doesn't provide embeddings - recommend using Voyage AI
		return null;
	}
}

