<?php
/**
 * Abstract AI Provider Base Class
 *
 * Provides common functionality for all AI providers.
 *
 * @package Askany
 * @since 1.0.0
 */

namespace Askany\Providers;

/**
 * Abstract base class for AI providers.
 */
abstract class AbstractProvider implements AIProviderInterface {
	/**
	 * API key for the provider.
	 *
	 * @var string
	 */
	protected $api_key;

	/**
	 * API endpoint URL.
	 *
	 * @var string
	 */
	protected $api_url;

	/**
	 * Constructor.
	 *
	 * @param string $api_key API key for the provider.
	 * @param string $api_url Optional custom API URL.
	 */
	public function __construct( string $api_key, string $api_url = '' ) {
		$this->api_key = $api_key;
		$this->api_url = ! empty( $api_url ) ? $api_url : $this->get_default_endpoint();
	}

	/**
	 * Make an HTTP request to the provider API.
	 *
	 * @param string $url API endpoint URL.
	 * @param array $data Request data.
	 * @param array $headers Additional headers.
	 * @return array|false Response data or false on failure.
	 */
	protected function make_request( string $url, array $data, array $headers = array() ) {
		$json_body = wp_json_encode( $data );
		if ( false === $json_body ) {
			$this->last_error = 'JSON encoding failed';
			// error_log( 'Provider API: JSON encoding failed' );
			return false;
		}

		$default_headers = array(
			'Content-Type' => 'application/json',
		);

		$args = array(
			'method'  => 'POST',
			'timeout' => 30,
			'headers' => array_merge( $default_headers, $headers ),
			'body'    => $json_body,
		);

		$response = wp_remote_post( $url, $args );

		if ( is_wp_error( $response ) ) {
			$this->last_error = $response->get_error_message();
			// error_log( 'Provider API Error: ' . $response->get_error_message() );
			return false;
		}

		$response_code = wp_remote_retrieve_response_code( $response );
		$response_body = wp_remote_retrieve_body( $response );

		if ( 200 !== $response_code ) {
			// Try to extract error message from response
			$decoded = json_decode( $response_body, true );
			if ( $decoded && isset( $decoded['error']['message'] ) ) {
				$this->last_error = $decoded['error']['message'];
			} else {
				$this->last_error = "HTTP {$response_code}: " . substr( $response_body, 0, 200 );
			}
			// error_log( "Provider API Error: HTTP {$response_code} - {$response_body}" );
			return false;
		}

		$decoded = json_decode( $response_body, true );
		if ( null === $decoded ) {
			$this->last_error = 'Failed to decode JSON response';
			// error_log( 'Provider API: Failed to decode JSON response' );
			return false;
		}

		return $decoded;
	}

	/**
	 * Last error message from API.
	 *
	 * @var string
	 */
	protected $last_error = '';

	/**
	 * Get the last error message.
	 *
	 * @return string
	 */
	public function get_last_error(): string {
		return $this->last_error;
	}

	/**
	 * {@inheritdoc}
	 */
	public function test_connection( array $options = array() ): array {
		if ( empty( $this->api_key ) ) {
			return array(
				'status'     => 'error',
				'message'    => sprintf( '%s API key is not configured', $this->get_provider_display_name() ),
				'details'    => 'Please set your API key in the plugin settings',
				'error_code' => 'missing_key',
			);
		}

		// Simple test message
		$test_messages = array(
			array(
				'role'    => 'user',
				'content' => 'Say "Hello" to test the connection.',
			),
		);

		try {
			// Merge test options with provided options (model, etc.)
			$request_options = array_merge( array( 'max_tokens' => 50 ), $options );
			
			$response = $this->send_chat_request( $test_messages, $request_options );

			if ( ! $response || empty( $response['text'] ) ) {
				$error_details = ! empty( $this->last_error ) ? $this->last_error : 'No response received from API. Check your API key and endpoint URL.';
				
				return array(
					'status'     => 'error',
					'message'    => sprintf( '%s connection failed', $this->get_provider_display_name() ),
					'details'    => $error_details,
					'error_code' => 'no_response',
				);
			}

			return array(
				'status'     => 'success',
				'message'    => sprintf( '%s connection successful', $this->get_provider_display_name() ),
				'details'    => 'Response: ' . esc_html( substr( $response['text'], 0, 100 ) ),
				'error_code' => null,
			);
		} catch ( \Exception $e ) {
			return array(
				'status'     => 'error',
				'message'    => sprintf( '%s connection error', $this->get_provider_display_name() ),
				'details'    => $e->getMessage(),
				'error_code' => 'exception',
			);
		}
	}
}
