<?php

namespace Limb_Chatbot\Includes\AI_Providers\Grok;

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\Utilities\AI_Model_Utility;

/**
 * Class Grok
 *
 * AI Provider implementation for xAI (Grok).
 *
 * @package Limb_Chatbot\Includes\AI_Providers\Grok
 * @since 1.0.12
 */
class Grok extends AI_Provider implements Config_Dependent_Interface {

	/**
	 * Base URL for xAI API.
	 *
	 * @var string
	 * @since 1.0.12
	 */
	const API_BASE_URL = 'https://api.x.ai/';

	/**
	 * xAI API version endpoint.
	 *
	 * @var string
	 * @since 1.0.12
	 */
	const API_VERSION = 'v1';

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

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

	/*** Unique ID for Grok provider.
	 *
	 * @var string
	 * @since 1.0.12
	 */
	public static string $id = 'grok';

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

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

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

	/**
	 * Validates whether the given configuration contains valid API credentials for xAI.
	 *
	 * Validates by attempting to list available models from the xAI API.
	 * Handles xAI-specific error codes:
	 * - 400: invalid_request_error - Invalid request body format
	 * - 401: authentication_error - Wrong API key
	 * - 422: validation_error - Invalid parameters
	 * - 429: rate_limit_error - Rate limit reached
	 *
	 * @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.12
	 *
	 */
	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,
						__( 'xAI 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,
						__( 'xAI 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,
						__( 'xAI API server error. Please retry after a brief wait.', 'limb-chatbot' ),
						$e->get_error_data()
					);

				default:
					throw $e;
			}
		}
	}

	/**
	 * Returns the default embedding model for xAI.
	 *
	 * Note: xAI does not provide embeddings.
	 *
	 * @return null xAI does not support embeddings.
	 * @since 1.0.12
	 */
	public function get_default_embedding_model() {
		// xAI doesn't provide embeddings
		return null;
	}
}
