<?php
/**
 * Gemini provider.
 *
 * @package Ugcify\AI
 */

namespace Ugcify\AI;

use WP_Error;

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

class GeminiProvider extends AbstractAIProvider {
	private const API_URL_BASE = 'https://generativelanguage.googleapis.com/v1beta/models/';

	/**
	 * Provider slug.
	 *
	 * @var string
	 */
	protected $provider = 'gemini';

	/**
	 * Analyze hotspot suggestions.
	 *
	 * @param array<string,mixed>             $image_source Image source block info.
	 * @param array<int,array<string,mixed>>  $candidates Candidate products.
	 * @param array<string,mixed>             $context Review context.
	 * @return array<string,mixed>|WP_Error
	 */
	public function analyze_hotspots( array $image_source, array $candidates, array $context = array() ) {
		$api_key = $this->get_api_key();
		if ( '' === $api_key ) {
			return new WP_Error( 'missing_api_key', __( 'Gemini API key is missing.', 'ugcify' ) );
		}

		$image_payload = $this->get_image_payload( $image_source );
		if ( is_wp_error( $image_payload ) ) {
			return $image_payload;
		}

		if ( empty( $image_payload['data'] ) && ! empty( $image_payload['url'] ) ) {
			$image_payload = $this->download_image( (string) $image_payload['url'], (string) $image_payload['media_type'] );
			if ( is_wp_error( $image_payload ) ) {
				return $image_payload;
			}
		}

		$response = wp_remote_post(
			self::API_URL_BASE . rawurlencode( $this->get_model() ) . ':generateContent?key=' . rawurlencode( $api_key ),
			array(
				'timeout' => 60,
				'headers' => array(
					'content-type' => 'application/json',
				),
				'body'    => wp_json_encode(
					array(
						'contents' => array(
							array(
								'role'  => 'user',
								'parts' => array(
									array(
										'text' => $this->build_instruction_text( $candidates, $context, (int) $this->settings['max_suggestions'] ),
									),
									array(
										'inline_data' => array(
											'mime_type' => (string) $image_payload['media_type'],
											'data'      => (string) $image_payload['data'],
										),
									),
								),
							),
						),
					)
				),
			)
		);

		if ( is_wp_error( $response ) ) {
			return new WP_Error( 'provider_request_failed', $response->get_error_message() );
		}

		$status = (int) wp_remote_retrieve_response_code( $response );
		if ( $status < 200 || $status >= 300 ) {
			return new WP_Error( 'provider_http_error', __( 'Gemini request failed.', 'ugcify' ) );
		}

		$decoded = json_decode( (string) wp_remote_retrieve_body( $response ), true );
		if ( ! is_array( $decoded ) ) {
			return new WP_Error( 'invalid_provider_response', __( 'Invalid Gemini response.', 'ugcify' ) );
		}

		$text = $this->collect_text( $decoded );
		$json = $this->extract_json_object( $text );
		if ( ! is_array( $json ) ) {
			return new WP_Error( 'invalid_provider_json', __( 'Gemini did not return valid JSON.', 'ugcify' ) );
		}

		return $json;
	}

	/**
	 * Download remote image for Gemini inline data.
	 *
	 * @param string $url Image URL.
	 * @param string $fallback_mime Fallback MIME.
	 * @return array<string,string>|WP_Error
	 */
	private function download_image( string $url, string $fallback_mime ) {
		$response = wp_remote_get(
			$url,
			array(
				'timeout' => 30,
			)
		);

		if ( is_wp_error( $response ) ) {
			return new WP_Error( 'image_read_failed', $response->get_error_message() );
		}

		$status = (int) wp_remote_retrieve_response_code( $response );
		if ( $status < 200 || $status >= 300 ) {
			return new WP_Error( 'image_read_failed', __( 'Failed to download image file.', 'ugcify' ) );
		}

		$body = (string) wp_remote_retrieve_body( $response );
		if ( '' === $body ) {
			return new WP_Error( 'image_read_failed', __( 'Failed to read image file.', 'ugcify' ) );
		}

		$content_type = wp_remote_retrieve_header( $response, 'content-type' );
		$mime_type    = is_string( $content_type ) && '' !== $content_type ? trim( explode( ';', $content_type )[0] ) : $fallback_mime;

		return array(
			'media_type' => $mime_type ?: 'image/jpeg',
			'data'       => base64_encode( $body ),
			'url'        => $url,
		);
	}

	/**
	 * Collect Gemini response text.
	 *
	 * @param array<string,mixed> $decoded Response.
	 * @return string
	 */
	private function collect_text( array $decoded ): string {
		$text = '';
		$candidates = isset( $decoded['candidates'] ) && is_array( $decoded['candidates'] ) ? $decoded['candidates'] : array();
		foreach ( $candidates as $candidate ) {
			if ( ! is_array( $candidate ) || empty( $candidate['content']['parts'] ) || ! is_array( $candidate['content']['parts'] ) ) {
				continue;
			}

			foreach ( $candidate['content']['parts'] as $part ) {
				if ( is_array( $part ) && isset( $part['text'] ) ) {
					$text .= (string) $part['text'];
				}
			}
		}

		return $text;
	}
}
