<?php

namespace RistrettoApps\Spawnster\Services;

use Spawnster;
use RistrettoApps\Spawnster\Base\Constants;

/**
 * Provides services for interacting with Google Search API.
 *
 * @package    Spawnster
 * @subpackage Spawnster/Services
 * @author     Ristretto Apps
 */
class GoogleSearchService {

	/**
	 * This variable stores the Google API key.
	 *
	 * @var string $api_key The Google API key.
	 */
	private $api_key;

	/**
	 * This variable stores the Google Search Engine ID.
	 *
	 * @var string $search_engine_id The Google Search Engine ID.
	 */
	private $search_engine_id;

	/**
	 * Remote server URL for fetching API keys.
	 *
	 * @var string $remote_api_url The remote server URL.
	 */
	private $remote_api_url;

	/**
	 * Constructor for the GoogleSearchService class.
	 *
	 * @param string $api_key The Google API key.
	 * @param string $search_engine_id The Google Search Engine ID.
	 */
	public function __construct( string $api_key = '', string $search_engine_id = '' ) {
		// Set remote API URL from constants
		$this->remote_api_url = Constants::SPAWNSTER_REMOTE_GOOGLE_API_URL;
		
		// Try to get API keys from remote server first, fallback to WordPress options
		$remote_keys = $this->get_remote_api_keys();
		$this->api_key = $api_key ?: $remote_keys['api_key'];
		$this->search_engine_id = $search_engine_id ?: $remote_keys['search_engine_id'];
	}

	/**
	 * Fetch API keys from remote server using WordPress HTTP API.
	 *
	 * @return array Array containing 'api_key' and 'search_engine_id'.
	 */
	private function get_remote_api_keys(): array {
		// Check if we have cached API keys (cache for 1 hour)
		$cached_keys = get_transient( 'spawnster_remote_google_keys' );
		if ( $cached_keys !== false ) {
			return $cached_keys;
		}

		// Try to fetch from remote server using WordPress HTTP API
		$keys = $this->fetch_api_keys_with_wp_http();
		
		if ( ! empty( $keys['api_key'] ) && ! empty( $keys['search_engine_id'] ) ) {
			// Cache the API keys for 1 hour
			set_transient( 'spawnster_remote_google_keys', $keys, HOUR_IN_SECONDS );
			return $keys;
		}

		// Fallback to WordPress options if remote fetch fails
		return array(
			'api_key' => Spawnster::get_option( 'spawnster_google_api_key' ),
			'search_engine_id' => Spawnster::get_option( 'spawnster_google_search_engine_id' )
		);
	}

	/**
	 * Fetch API keys using WordPress HTTP API.
	 *
	 * @return array Array containing 'api_key' and 'search_engine_id'.
	 */
	private function fetch_api_keys_with_wp_http(): array {
		error_log('Spawnster: Attempting to fetch API keys from: ' . $this->remote_api_url);

		$response = wp_remote_get( $this->remote_api_url, array(
			'timeout' => 10,
			'user-agent' => 'Spawnster/1.0',
			'sslverify' => false // Only if you have SSL issues
		) );

		if ( is_wp_error( $response ) ) {
			error_log('Spawnster: WordPress HTTP API error: ' . $response->get_error_message());
			return array( 'api_key' => '', 'search_engine_id' => '' );
		}

		$status_code = wp_remote_retrieve_response_code( $response );
		if ( $status_code !== 200 ) {
			error_log('Spawnster: HTTP request failed with status code: ' . $status_code);
			return array( 'api_key' => '', 'search_engine_id' => '' );
		}

		$body = wp_remote_retrieve_body( $response );
		error_log('Spawnster: HTTP response body length: ' . strlen($body));
		error_log('Spawnster: HTTP response body (first 200 chars): ' . substr($body, 0, 200));

		return $this->parse_json_response( $body );
	}

	/**
	 * Parse JSON response and validate keys.
	 *
	 * @param string $json_string The JSON string to parse.
	 * @return array Array containing 'api_key' and 'search_engine_id'.
	 */
	private function parse_json_response( string $json_string ): array {
		$json_data = json_decode( $json_string, true );
		
		if ( json_last_error() !== JSON_ERROR_NONE ) {
			error_log('Spawnster: JSON decode error: ' . json_last_error_msg());
			return array( 'api_key' => '', 'search_engine_id' => '' );
		}

		error_log('Spawnster: JSON parsed successfully');

		// Extract and validate the keys
		$api_key = trim( $json_data['search_api_key'] ?? '' );
		$search_engine_id = trim( $json_data['search_engine_id'] ?? '' );
		
		error_log('Spawnster: API key length: ' . strlen($api_key));
		error_log('Spawnster: Search engine ID length: ' . strlen($search_engine_id));
		
		// Basic validation for API key
		$api_key_valid = strlen( $api_key ) >= 30 && preg_match( '/^[A-Za-z0-9_-]+$/', $api_key );
		
		// Basic validation for search engine ID (Google CSE IDs are typically 17 characters)
		$search_engine_id_valid = strlen( $search_engine_id ) >= 10 && preg_match( '/^[A-Za-z0-9_-]+$/', $search_engine_id );

		error_log('Spawnster: API key valid: ' . ($api_key_valid ? 'yes' : 'no'));
		error_log('Spawnster: Search engine ID valid: ' . ($search_engine_id_valid ? 'yes' : 'no'));

		if ( $api_key_valid && $search_engine_id_valid ) {
			error_log('Spawnster: Both keys are valid, returning them');
			return array(
				'api_key' => $api_key,
				'search_engine_id' => $search_engine_id
			);
		}

		error_log('Spawnster: Keys failed validation');
		return array( 'api_key' => '', 'search_engine_id' => '' );
	}

	/**
	 * Check if wget is available on the system.
	 *
	 * @return bool True if wget is available, false otherwise.
	 */
	private function is_wget_available(): bool {
		$output = shell_exec( 'which wget 2>/dev/null' );
		return ! empty( $output );
	}

	/**
	 * Search for content using Google Search API.
	 *
	 * @param string $query The search query.
	 * @param int    $num   The number of results to return.
	 * @return array|WP_Error The search results or an error message.
	 */
	public function search( string $query, int $num = 10 ): array|WP_Error {
		if ( empty( $this->api_key ) || empty( $this->search_engine_id ) ) {
			return new WP_Error( 'google_search_error', 'Google API key or Search Engine ID not configured.' );
		}

		$url = 'https://www.googleapis.com/customsearch/v1';
		$args = array(
			'key' => $this->api_key,
			'cx'  => $this->search_engine_id,
			'q'   => $query,
			'num' => $num,
		);

		$response = wp_remote_get( add_query_arg( $args, $url ) );

		if ( is_wp_error( $response ) ) {
			return $response;
		}

		$body = wp_remote_retrieve_body( $response );
		$data = json_decode( $body, true );

		if ( isset( $data['error'] ) ) {
			return new WP_Error( 'google_search_error', $data['error']['message'] );
		}

		return $data;
	}

	/**
	 * Extract content from search results.
	 *
	 * @param array $search_results The search results from Google.
	 * @return array The extracted content.
	 */
	public function extract_content_from_results( array $search_results ): array {
		$contents = array();

		if ( ! isset( $search_results['items'] ) ) {
			return $contents;
		}

		foreach ( $search_results['items'] as $item ) {
			$content = array(
				'title'   => $item['title'] ?? '',
				'snippet' => $item['snippet'] ?? '',
				'link'    => $item['link'] ?? '',
			);

			// Try to fetch the full content from the URL
			$full_content = $this->fetch_url_content( $item['link'] ?? '' );
			if ( $full_content ) {
				$content['full_content'] = $full_content;  // Fixed: was $content, should be $full_content
			}

			$contents[] = $content;
		}

		return $contents;
	}

	/**
	 * Fetch content from a URL.
	 *
	 * @param string $url The URL to fetch content from.
	 * @return string|false The content or false on failure.
	 */
	private function fetch_url_content( string $url ): string|false {
		if ( empty( $url ) ) {
			return false;
		}

		$response = wp_remote_get( $url, array(
			'timeout' => 30,
			'user-agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
		) );

		if ( is_wp_error( $response ) ) {
			return false;
		}

		$body = wp_remote_retrieve_body( $response );
		
		// Basic content extraction - remove HTML tags and clean up
		$content = wp_strip_all_tags( $body );
		$content = preg_replace( '/\s+/', ' ', $content ); // Replace multiple spaces with single space
		$content = trim( $content );

		// Limit content length to avoid token limits
		return substr( $content, 0, 8000 );
	}
} 