<?php
/**
 * GigaChat AI Provider Class
 *
 * Integration with GigaChat (Sber) for text and image generation.
 *
 * @package SmartyPress_AI_Engine
 * @since 1.1.0
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * GigaChat Provider class
 */
class SmartyPress_AI_GigaChat_Provider extends SmartyPress_AI_AI_Provider {

	/**
	 * GigaChat client instance
	 *
	 * @var SmartyPress_AI_GigaChat_Client
	 */
	private $client;

	/**
	 * API scope
	 *
	 * @var string
	 */
	private $scope;

	/**
	 * SSL verify setting
	 *
	 * @var bool
	 */
	private $verify_ssl;

	/**
	 * Constructor
	 *
	 * @param string $auth_key   Authorization key (base64 of client_id:client_secret).
	 * @param string $scope      API scope.
	 * @param string $model      Default model name.
	 * @param bool   $verify_ssl Whether to verify SSL certificate.
	 * @param string $base_url   GigaChat API base URL.
	 */
	public function __construct( $auth_key, $scope = 'GIGACHAT_API_PERS', $model = 'GigaChat-2', $verify_ssl = true, $base_url = 'https://gigachat.devices.sberbank.ru/api/v1' ) {
		parent::__construct( $auth_key, $model );
		$this->scope      = $scope;
		$this->verify_ssl = $verify_ssl;
		$this->client     = new SmartyPress_AI_GigaChat_Client( $auth_key, $scope, $verify_ssl, $base_url );
	}

	/**
	 * Generate content using GigaChat
	 *
	 * @param string $prompt The prompt to send to AI.
	 * @param array  $params Additional parameters.
	 * @return array Response with content or error.
	 */
	public function generate_content( $prompt, $params = array() ) {
		$system_prompt = isset( $params['system_prompt'] )
			? $params['system_prompt']
			: __( 'You are a helpful assistant for content generation.', 'smartypress-ai-engine' );

		$messages = array(
			array(
				'role'    => 'system',
				'content' => $system_prompt,
			),
			array(
				'role'    => 'user',
				'content' => $prompt,
			),
		);

		$model = ! empty( $params['model'] ) ? $params['model'] : $this->model;

		try {
			$result = $this->client->chat(
				$messages,
				$model,
				array(
					'temperature' => isset( $params['temperature'] ) ? $params['temperature'] : 0.7,
					'max_tokens'  => isset( $params['max_tokens'] ) ? $params['max_tokens'] : 2000,
				)
			);
		} catch ( Exception $e ) {
			$error_code = '';

			// Detect authentication errors.
			if ( stripos( $e->getMessage(), 'access token' ) !== false
				|| stripos( $e->getMessage(), 'OAuth' ) !== false
				|| stripos( $e->getMessage(), 'unauthorized' ) !== false
				|| stripos( $e->getMessage(), 'authorization' ) !== false
			) {
				$error_code = 'api_key_invalid';
			}

			// Log the error.
			if ( class_exists( 'SmartyPress_AI_Logger' ) ) {
				$log_request = array(
					'model'    => $model,
					'messages' => array(
						array( 'role' => 'system', 'content' => $system_prompt ),
						array( 'role' => 'user', 'content' => $prompt ),
					),
				);
				SmartyPress_AI_Logger::log_api_error(
					$this->get_provider_name(),
					$this->client->get_endpoint_url( SmartyPress_AI_GigaChat_Client::CHAT_ENDPOINT ),
					$log_request,
					array(
						'code' => 0,
						'body' => $e->getMessage(),
					),
					$e->getMessage(),
					$error_code
				);
			}

			return array(
				'success'    => false,
				'error'      => $e->getMessage(),
				'error_code' => $error_code,
			);
		}

		if ( ! $result['success'] ) {
			$error_code = '';

			// Detect auth errors from HTTP response.
			$code = isset( $result['code'] ) ? $result['code'] : 0;
			if ( in_array( $code, array( 401, 403 ), true ) ) {
				$error_code = 'api_key_invalid';

				// Clear cached token on auth errors.
				$this->client->get_auth_manager()->clear_cache();
			}

			// Log the error.
			if ( class_exists( 'SmartyPress_AI_Logger' ) ) {
				$log_request = array(
					'model'       => $model,
					'temperature' => isset( $params['temperature'] ) ? $params['temperature'] : 0.7,
					'max_tokens'  => isset( $params['max_tokens'] ) ? $params['max_tokens'] : 2000,
					'messages'    => array(
						array( 'role' => 'system', 'content' => $system_prompt ),
						array( 'role' => 'user', 'content' => $prompt ),
					),
				);
				SmartyPress_AI_Logger::log_api_error(
					$this->get_provider_name(),
					$this->client->get_endpoint_url( SmartyPress_AI_GigaChat_Client::CHAT_ENDPOINT ),
					$log_request,
					array(
						'code' => $code,
						'body' => isset( $result['error'] ) ? $result['error'] : '',
					),
					isset( $result['error'] ) ? $result['error'] : __( 'Unknown error', 'smartypress-ai-engine' ),
					$error_code
				);
			}

			return array(
				'success'    => false,
				'error'      => isset( $result['error'] ) ? $result['error'] : __( 'Unknown GigaChat API error', 'smartypress-ai-engine' ),
				'error_code' => $error_code,
			);
		}

		// Extract content from OpenAI-compatible response format.
		$content = isset( $result['data']['choices'][0]['message']['content'] )
			? $result['data']['choices'][0]['message']['content']
			: '';

		$usage = isset( $result['data']['usage'] ) ? $result['data']['usage'] : array();

		// Clean markdown code blocks that GigaChat sometimes adds.
		$content = $this->clean_markdown_artifacts( $content );

		// Log successful request.
		if ( class_exists( 'SmartyPress_AI_Logger' ) ) {
			$log_request = array(
				'model'       => $model,
				'temperature' => isset( $params['temperature'] ) ? $params['temperature'] : 0.7,
				'max_tokens'  => isset( $params['max_tokens'] ) ? $params['max_tokens'] : 2000,
				'messages'    => array(
					array( 'role' => 'system', 'content' => $system_prompt ),
					array( 'role' => 'user', 'content' => $prompt ),
				),
			);
			SmartyPress_AI_Logger::log_api_success(
				$this->get_provider_name(),
				$this->client->get_endpoint_url( SmartyPress_AI_GigaChat_Client::CHAT_ENDPOINT ),
				$log_request,
				array(
					'code'    => 200,
					'content' => $content,
					'usage'   => $usage,
				)
			);
		}

		// Record token usage for statistics.
		if ( class_exists( 'SmartyPress_AI_Token_Tracker' ) ) {
			SmartyPress_AI_Token_Tracker::record( array(
				'provider' => $this->get_provider_name(),
				'model'    => $model,
				'usage'    => $usage,
			) );
		}

		return array(
			'success' => true,
			'content' => $content,
			'usage'   => $usage,
		);
	}

	/**
	 * Generate image using GigaChat
	 *
	 * @param string $prompt Image generation prompt.
	 * @param array  $params Additional parameters.
	 * @return array Response with image data or error.
	 */
	public function generate_image( $prompt, $params = array() ) {
		try {
			$result = $this->client->create_image( $prompt, $params );
		} catch ( Exception $e ) {
			return array(
				'success' => false,
				'error'   => $e->getMessage(),
			);
		}

		if ( ! $result['success'] ) {
			return $result;
		}

		return array(
			'success'  => true,
			'b64_json' => $result['b64_json'],
			'model'    => 'gigachat-image',
			'usage'    => array(),
		);
	}

	/**
	 * Validate API key (auth key)
	 *
	 * @return bool True if valid, false otherwise.
	 */
	public function validate_api_key() {
		try {
			$messages = array(
				array(
					'role'    => 'user',
					'content' => __( 'Say "Hello"', 'smartypress-ai-engine' ),
				),
			);

			$result = $this->client->chat(
				$messages,
				$this->model,
				array( 'max_tokens' => 10 )
			);

			return isset( $result['success'] ) ? $result['success'] : false;
		} catch ( Exception $e ) {
			return false;
		}
	}

	/**
	 * Get available text models
	 *
	 * @return array List of available models with metadata.
	 */
	public function get_available_models() {
		return SmartyPress_AI_GigaChat_Models::get_model_descriptions();
	}

	/**
	 * Get available image generation models
	 *
	 * @return array List of image models.
	 */
	public function get_available_image_models() {
		return SmartyPress_AI_GigaChat_Models::get_image_models();
	}

	/**
	 * Clean markdown artifacts from GigaChat response
	 *
	 * @param string $content Raw content from API.
	 * @return string Cleaned content.
	 */
	private function clean_markdown_artifacts( $content ) {
		// Remove markdown code blocks (``` or ```html etc.) at start.
		$content = preg_replace( '/^```[a-z]*\s*/i', '', $content );
		// Remove markdown code blocks at end.
		$content = preg_replace( '/\s*```$/i', '', $content );

		// Also handle HTML-escaped versions.
		$content = preg_replace( '/<br\s*\/?>\s*```\s*$/i', '', $content );
		$content = preg_replace( '/^```\s*<br\s*\/?>/i', '', $content );

		// Clean up any remaining standalone ``` at start/end.
		$content = preg_replace( '/^```\s*/i', '', $content );
		$content = preg_replace( '/\s*```$/i', '', $content );

		return trim( $content );
	}
}
