<?php
/**
 * =====================================================================
 *  WordAI Agent — Google Gemini Embedding API Handler
 *  -------------------------------------------------------------------
 *  - Provider-specific embedding engine for Gemini
 *  - Works through the central Router (SftcyWordaiAiProviderRouter)
 *  - Full multi-provider support for Agent Indexing
 * =====================================================================
 */

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

class SftcyWordaiAgentGemini {

    /** Provider slug stored in DB (embeddings.provider column) */
    const PROVIDER = 'google';

    /** Default Gemini embedding model */
    const DEFAULT_EMBEDDING_MODEL = 'gemini-embedding-001';

    private static function get_api_key() {
        $settings = (array) maybe_unserialize( get_option( 'sftcy-wordai-google-gemini-apisettings-data' ) );
        return isset( $settings['wordai-google-gemini-api-key-data'] )
            ? trim( (string) $settings['wordai-google-gemini-api-key-data'] )
            : '';
    }

    /**
     * =====================================================================
     *  CREATE EMBEDDINGS
     * =====================================================================
     * Required return format:
     *
     * [
     *   'status'     => 'success' | 'fail',
     *   'feedbackMsg'=> '...',
     *   'embeddings' => [ [float,...], [float,...], ... ],
     *   'provider'   => 'google',
     *   'model'      => 'text-embedding-004'
     * ]
     * =====================================================================
     */
    public static function create_embeddings( $texts = [], $model = self::DEFAULT_EMBEDDING_MODEL ) {

        if ( empty( $texts ) ) {
            return [
                'status'      => 'fail',
                'feedbackMsg' => 'No text provided for Gemini embedding.',
            ];
        }

        if ( empty( $model ) ) {
            $model = self::DEFAULT_EMBEDDING_MODEL;
        }

        $api_key = self::get_api_key();
        if ( $api_key === '' ) {
            return [
                'status'      => 'fail',
                'feedbackMsg' => 'Google Gemini API key is missing.',
            ];
        }

        $embeddings = [];
        foreach ( (array) $texts as $chunk ) {
            $response = wp_remote_post(
                sprintf(
                    'https://generativelanguage.googleapis.com/v1beta/models/%s:embedContent',
                    rawurlencode( $model )
                ),
                [
                    'headers'   => [
                        'Content-Type'   => 'application/json',
                        'x-goog-api-key' => $api_key,
                    ],
                    'body'      => wp_json_encode(
                        [
                            'model' => 'models/' . $model,
                            'content' => [
                                'parts' => [
                                    [ 'text' => (string) $chunk ],
                                ],
                            ],
                            'taskType' => 'RETRIEVAL_DOCUMENT',
                            'outputDimensionality' => 768,
                        ]
                    ),
                    'timeout'   => 40,
                    'sslverify' => class_exists( 'SftcyWordaiBase' ) ? SftcyWordaiBase::sc_wordai_should_verify_ssl() : true,
                ]
            );

            if ( is_wp_error( $response ) ) {
                return [
                    'status'      => 'fail',
                    'feedbackMsg' => 'Embedding request failed: ' . $response->get_error_message(),
                ];
            }

            $code = (int) wp_remote_retrieve_response_code( $response );
            $raw  = wp_remote_retrieve_body( $response );
            $json = json_decode( $raw, true );

            if ( $code !== 200 || empty( $json['embedding']['values'] ) ) {
                return [
                    'status'      => 'fail',
                    'feedbackMsg' => 'Embedding error: ' . ( $json['error']['message'] ?? 'Unknown API error.' ),
                ];
            }

            $embeddings[] = $json['embedding']['values'];
        }

        // ==== VALIDATE ====
        if ( empty( $embeddings ) ) {
            return [
                'status'      => 'fail',
                'feedbackMsg' => 'Gemini API returned no embeddings.',
            ];
        }

        // ==== FINAL NORMALIZED OPENAI-COMPATIBLE RETURN ====
        return [
            'status'      => 'success',
            'feedbackMsg' => 'Gemini embeddings created.',
            'embeddings'  => $embeddings,
            'provider'    => self::PROVIDER,
            'model'       => $model,
        ];
    }


    /**
     * =====================================================================
     *  CHUNK TEXT — reuse OpenAI logic for consistency
     * =====================================================================
     */
    public static function chunk_text( $text = '', $chunk_size = 500 ) {
        return SftcyWordaiAgentOpenai::chunk_text( $text, $chunk_size );
    }

    /**
     * =====================================================================
     *  COST ESTIMATE FOR GEMINI
     * =====================================================================
     * Pricing used (Feb 2025):
     *
     *  Gemini 2.5 Flash Embedding (text):  $0.13 / 1M tokens input
     *  Gemini 2.5 Pro  Embedding:         $0.40 / 1M tokens input
     *
     *  → We use the "Flash" price unless model includes "pro"
     *
     * =====================================================================
     */
    public static function estimate_cost( $total_words = 0, $model = self::DEFAULT_EMBEDDING_MODEL ) {

        if ( $total_words <= 0 ) {
            return [
                'status'      => 'fail',
                'feedbackMsg' => 'No valid words provided for Gemini estimation.',
            ];
        }

        if ( empty( $model ) ) {
            $model = self::DEFAULT_EMBEDDING_MODEL;
        }

        // Rough token approximation — same as OpenAI
        $tokens = (int) ceil( $total_words / 0.75 );

        // Pricing selection
        $price_per_million = ( stripos( $model, 'pro' ) !== false )
            ? 0.40        // Pro model
            : 0.13;       // Flash / default

        $cost = ( $tokens / 1_000_000 ) * $price_per_million;

        return [
            'status'         => 'success',
            'total_tokens'   => $tokens,
            'estimated_cost' => $cost,
            'provider'       => self::PROVIDER,
            'model'          => $model,
            'feedbackMsg'    => 'Gemini cost estimated successfully.',
        ];
    }

    /**
     * =====================================================================
     *  COMPUTE CHUNK HASH
     * =====================================================================
     */
    public static function compute_chunk_hash( $chunk_text ) {
        return SftcyWordaiAgentOpenai::compute_chunk_hash( $chunk_text );
    }

    /**
     * =====================================================================
     *  STORE EMBEDDING VECTOR
     * =====================================================================
     * Uses SAME table as OpenAI — provider+model+chunk_hash keeps uniqueness.
     * =====================================================================
     */
    public static function store_embedding( $source_id, $chunk_text, $embedding, $model = self::DEFAULT_EMBEDDING_MODEL ) {
        global $wpdb;

        if ( empty( $model ) ) {
            $model = self::DEFAULT_EMBEDDING_MODEL;
        }

        $table      = $wpdb->prefix . 'wordai_agent_embeddings';
        $provider   = self::PROVIDER;
        $chunk_hash = self::compute_chunk_hash( $chunk_text );

        // Avoid duplicates
        $exists = $wpdb->get_var(
            $wpdb->prepare(
                "SELECT id FROM {$table}
                 WHERE source_id=%d AND provider=%s AND model=%s AND chunk_hash=%s
                 LIMIT 1",
                $source_id,
                $provider,
                $model,
                $chunk_hash
            )
        );

        if ( $exists ) {
            return;
        }

        $wpdb->insert(
            $table,
            [
                'source_id'  => $source_id,
                'chunk_text' => maybe_serialize( $chunk_text ),
                'embedding'  => maybe_serialize( $embedding ),
                'model'      => $model,
                'provider'   => $provider,
                'chunk_hash' => $chunk_hash,
                'created_at' => current_time( 'mysql' ),
            ],
            [ '%d', '%s', '%s', '%s', '%s', '%s', '%s' ]
        );
    }
}
