<?php
/**
 * Costudio_Search_Engine_Gemini
 *
 * Web search engine using Google Gemini's native Search Grounding.
 * Used when the user wants to use their own Gemini key for web research
 * instead of the ContentOS native engine or other external providers.
 *
 * @package Contentosapp_Studio
 * @since   3.3.0
 */

defined( 'ABSPATH' ) || exit;

class Costudio_Search_Engine_Gemini {

	/**
	 * Execute a search using Gemini Grounding.
	 *
	 * @param  string $query
	 * @param  string $model_override Optional model to use.
	 * @return array{ok:bool,sources:array<int,array{url:string,title:string,snippet:string}>,summary_markdown:string,fallback_md:string,provider?:string,model?:string,model_used?:string}
	 */
	public function search( string $query, string $model_override = '', string $api_key_override = '' ): array {
		$settings = costudio_settings();

		// Use the Web Search provider's OWN key — never the text provider's
		// `ai_api_key`. When the text provider is not Gemini (e.g. Claude/OpenAI),
		// `ai_api_key` is that provider's key and grounding fails silently with a 401.
		$api_key = '' !== $api_key_override
			? $api_key_override
			: ( $settings ? (string) $settings->get( 'search_api_key', '' ) : '' );
		if ( '' === $api_key && $settings ) {
			$api_key = (string) $settings->get( 'ai_api_key', '' ); // last-resort fallback
		}

		// Model priority: explicit search override → configured search model →
		// a safe Gemini default (never the text model, which may be a non-Gemini slug).
		$model = $model_override;
		if ( empty( $model ) ) {
			$model = $settings ? (string) $settings->get( 'search_api_model', '' ) : '';
		}
		if ( empty( $model ) ) {
			$model = 'gemini-2.5-flash';
		}

		if ( empty( $api_key ) ) {
			return self::empty_result();
		}

		try {
			// Ensure we use a model that supports grounding if the user selected a legacy one.
			if ( strpos( $model, 'gemini' ) === false ) {
				$model = 'gemini-1.5-flash';
			}

			$adapter = new Costudio_Gemini_Adapter( $api_key, $model, true );

			$prompt = sprintf(
				"Atue como um pesquisador especializado. Realize uma busca detalhada sobre: \"%s\".\n"
				. "Forneça um resumo estruturado com os principais fatos, dados e informações relevantes para um artigo de blog.\n"
				. "É OBRIGATÓRIO citar as fontes (URLs) de onde as informações foram extraídas.",
				$query
			);

			// We use generateWithSearch which triggers the google_search tool.
			$text = $adapter->generateWithSearch( $prompt );

			// Map grounding chunks → structured sources, resolving the Vertex
			// grounding-redirect URLs to their real destination so they dedupe
			// against the user's externals and render cleanly. Empty when grounding
			// didn't fire (free tier / no billing) → caller uses `fallback_md`.
			$sources = array();
			foreach ( $adapter->get_last_grounding_sources() as $src ) {
				$url = isset( $src['url'] ) ? (string) $src['url'] : '';
				if ( '' === $url ) {
					continue;
				}
				if ( class_exists( 'Costudio_Url' ) && Costudio_Url::is_vertex_redirect( $url ) ) {
					$resolved = Costudio_Url::resolve_vertex_redirect( $url );
					if ( '' !== $resolved ) {
						$url = $resolved;
					}
				}
				$sources[] = array(
					'url'     => $url,
					'title'   => isset( $src['title'] ) ? (string) $src['title'] : '',
					'snippet' => isset( $src['snippet'] ) ? (string) $src['snippet'] : '',
				);
			}

			return array(
				'ok'               => '' !== $text || ! empty( $sources ),
				'sources'          => $sources,
				'summary_markdown' => '',
				'fallback_md'      => $text,
				'provider'         => 'gemini',
				'model'            => $model,
				'model_used'       => $model,
			);

		} catch ( \Throwable $e ) {
			costudio_log( 'gemini_search.error', [ 'error' => $e->getMessage() ], 'warning' );
			return self::empty_result();
		}
	}

	private static function empty_result(): array {
		return array(
			'ok'               => false,
			'sources'          => array(),
			'summary_markdown' => '',
			'fallback_md'      => '',
		);
	}
}
