<?php

namespace Limb_Chatbot\Includes\AI_Providers\Open_Router\Seeders;

use Exception;
use Limb_Chatbot\Includes\Data_Objects\AI_Model;
use Limb_Chatbot\Includes\Data_Objects\AI_Model_Meta;
use Limb_Chatbot\Includes\AI_Providers\Open_Router\Open_Router;
use Limb_Chatbot\Includes\AI_Providers\Open_Router\Services\Model_Filter_Service;
use Limb_Chatbot\Includes\Database_Strategies\WPDB;
use Limb_Chatbot\Includes\Services\Helper;

/**
 * Class AI_Models_Seeder
 *
 * Seeder class responsible for seeding AI models specific to the OpenRouter AI provider.
 * Fetches models dynamically from the OpenRouter API using AI_Model_Utility.
 * Filtering and parsing is delegated to Model_Filter_Service.
 *
 * @package Limb_Chatbot\Includes\AI_Providers\Open_Router\Seeders
 * @since 1.0.15
 */
class AI_Models_Seeder {

	/**
	 * Model filter service for filtering and parsing model data.
	 *
	 * @var Model_Filter_Service
	 * @since 1.0.14
	 */
	protected Model_Filter_Service $filter_service;

	/**
	 * WPDB database strategy instance.
	 *
	 * @var WPDB
	 * @since 1.0.15
	 */
	protected WPDB $wpdb_strategy;

	/**
	 * Constructor.
	 *
	 * @since 1.0.14
	 */
	public function __construct() {
		$this->filter_service = new Model_Filter_Service();
		$this->wpdb_strategy  = WPDB::instance();
	}

	/**
	 * Run the seeder to fetch and create AI models from OpenRouter API.
	 *
	 * @return void
	 * @throws Exception
	 * @since 1.0.14
	 */
	public function run() {
		try {
			$models = $this->fetch_models();

			if ( empty( $models ) ) {
				Helper::log( 'No models fetched from OpenRouter API', 'warning' );
				return;
			}

			Helper::log( sprintf( 'Fetched %d models from OpenRouter API', count( $models ) ) );

			// Filter for chat models with function calling (tools) support
			$chat_models = $this->filter_service->filter_chat_models( $models );

			// Get all existing OpenRouter models from database
			$existing_models = $this->get_existing_models();

			if ( empty( $existing_models ) ) {
				// No existing models - bulk insert all
				Helper::log( 'No existing models found - performing bulk insert' );
				$this->bulk_insert_models( $chat_models );
			} else {
				// Some models exist - split into new and existing
				Helper::log( 'Existing models found - processing updates and new inserts' );
				$this->process_models_with_existing( $chat_models, $existing_models );
			}

			$this->seed_embedding_models();

		} catch ( Exception $e ) {
			Helper::log( sprintf( 'Seeder failed with error: %s', $e->getMessage() ), 'error' );
			throw $e;
		}
	}

	/**
	 * Fetches models from the OpenRouter API using AI_Model_Utility.
	 *
	 * @return array Array of model data objects.
	 * @since 1.0.14
	 */
	protected function fetch_models(): array {
		try {
			$response = wp_remote_get( 'https://openrouter.ai/api/v1/models', [
				'timeout' => 60,
			] );

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

			$response_code = wp_remote_retrieve_response_code( $response );
			if ( $response_code !== 200 ) {
				return [];
			}

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

			if ( json_last_error() !== JSON_ERROR_NONE ) {
				return [];
			}

			if ( empty( $data->data ) || ! is_array( $data->data ) ) {
				return [];
			}
			return $data->data;

		} catch ( Exception $e ) {
			Helper::log( sprintf( 'Exception while fetching models: %s', $e->getMessage() ), 'error' );
			return [];
		}
	}

	/**
	 * Get all existing OpenRouter models from the database.
	 *
	 * @return array Associative array of model name => AI_Model object.
	 * @since 1.0.14
	 */
	protected function get_existing_models(): array {
		$models = AI_Model::where( [ 'ai_provider_id' => Open_Router::$id ] );
		$result = [];

		foreach ( $models as $model ) {
			$result[ $model->name ] = $model;
		}

		return $result;
	}

	/**
	 * Bulk insert all chat models when no existing models.
	 *
	 * Performs one INSERT query for all models and one INSERT query for all metas.
	 *
	 * @param array $chat_models Array of model data objects from API.
	 * @return void
	 * @throws Exception
	 * @since 1.0.14
	 */
	protected function bulk_insert_models( array $chat_models ): void {

		$models_data = [];
		$metas_data  = [];

		foreach ( $chat_models as $model_data ) {
			$model_name = $this->filter_service->get_model_name( $model_data );

			if ( empty( $model_name ) ) {
				continue;
			}

			$prepared = $this->prepare_model_data( $model_data );

			if ( ! empty( $prepared['model'] ) ) {
				$models_data[ $model_name ] = $prepared['model'];
				$metas_data[ $model_name ]  = $prepared['metas'];
			}
		}

		if ( empty( $models_data ) ) {
			return;
		}

		// Bulk insert models
		$inserted_ids = $this->bulk_insert_ai_models( $models_data );

		// Bulk insert metas with correct model IDs
		if ( ! empty( $inserted_ids ) ) {
			$this->bulk_insert_ai_model_metas( $metas_data, $inserted_ids );
		}
	}

	/**
	 * Process models when some already exist - update existing, bulk insert new.
	 *
	 * @param array $chat_models    Array of model data objects from API.
	 * @param array $existing_models Associative array of model name => AI_Model.
	 * @return void
	 * @throws Exception
	 * @since 1.0.14
	 */
	protected function process_models_with_existing( array $chat_models, array $existing_models ): void {
		$new_models_data = [];
		$new_metas_data  = [];

		foreach ( $chat_models as $model_data ) {
			$model_name = $this->filter_service->get_model_name( $model_data );

			if ( empty( $model_name ) ) {
				continue;
			}

			$prepared = $this->prepare_model_data( $model_data );

			if ( empty( $prepared['model'] ) ) {
				continue;
			}

			if ( isset( $existing_models[ $model_name ] ) ) {
				// Update existing model one-by-one
				$this->update_existing_model( $existing_models[ $model_name ], $prepared['model'], $prepared['metas'] );
			} else {
				// Collect for bulk insert
				$new_models_data[ $model_name ] = $prepared['model'];
				$new_metas_data[ $model_name ]  = $prepared['metas'];
			}
		}

		// Bulk insert new models
		if ( ! empty( $new_models_data ) ) {
			$inserted_ids = $this->bulk_insert_ai_models( $new_models_data );

			if ( ! empty( $inserted_ids ) ) {
				$this->bulk_insert_ai_model_metas( $new_metas_data, $inserted_ids );
			}
		}
	}

	/**
	 * Prepare model data from API model object.
	 *
	 * @param object $model_data Model data from API.
	 * @return array Array with 'model' and 'metas' keys.
	 * @since 1.0.14
	 */
	protected function prepare_model_data( $model_data ): array {
		$model_name = $this->filter_service->get_model_name( $model_data );

		if ( empty( $model_name ) ) {
			return [ 'model' => null, 'metas' => [] ];
		}

		// Use filter service for parsing
		$modalities = $this->filter_service->parse_modalities( $model_data );
		$endpoints  = $this->filter_service->parse_endpoints( $model_data );
		$features   = $this->filter_service->parse_features( $model_data );
		$metas      = $this->filter_service->parse_pricing( $model_data );

		// Add context length to metas
		$metas['context_length'] = $this->filter_service->get_context_length( $model_data );

		// Handle free variants - set costs to 0 but store original as paid_* metas
		$is_free_variant = $this->filter_service->is_free_variant( $model_data );
		$variant         = $this->filter_service->get_variant( $model_data );

		if ( $is_free_variant ) {
			// Store original costs as paid costs (if available from API)
			if ( $metas['input_token_cost'] > 0 ) {
				$metas['paid_input_token_cost'] = $metas['input_token_cost'];
			}
			if ( $metas['output_token_cost'] > 0 ) {
				$metas['paid_output_token_cost'] = $metas['output_token_cost'];
			}
			// Free variants have zero cost
			$metas['input_token_cost']  = 0;
			$metas['output_token_cost'] = 0;
		} else {
			// For paid models, store costs in both regular and paid_* metas
			$metas['paid_input_token_cost']  = $metas['input_token_cost'];
			$metas['paid_output_token_cost'] = $metas['output_token_cost'];
		}

		// Add variant meta if present
		if ( $variant ) {
			$metas['variant'] = $variant;
		}

		$model_attributes = [
			'label'              => $this->filter_service->get_model_label( $model_data ),
			'name'               => $model_name,
			'description'        => $this->filter_service->build_description( $model_data ),
			'ai_provider_id'     => Open_Router::$id,
			'fine_tuned'         => false,
			'status'             => AI_Model::STATUS_ACTIVE,
			'output_token_limit' => $this->filter_service->get_output_token_limit( $model_data ),
			'modalities'         => $modalities,
			'endpoints'          => $endpoints,
			'features'           => $features,
		];

		return [
			'model' => $model_attributes,
			'metas' => $metas,
		];
	}

	/**
	 * Bulk insert AI models into database.
	 *
	 * Uses a single INSERT query for all models, then fetches the inserted rows
	 * by their names to get the correct IDs.
	 *
	 * @param array $models_data Associative array of model_name => model_attributes.
	 * @return array Associative array of model_name => inserted_id.
	 * @throws Exception
	 * @since 1.0.14
	 */
	protected function bulk_insert_ai_models( array $models_data ): array {
		global $wpdb;

		if ( empty( $models_data ) ) {
			return [];
		}

		$table_name = $wpdb->prefix . AI_Model::TABLE_NAME;

		// Build the INSERT query - only include columns that exist in the table
		$columns = [ 'label', 'name', 'ai_provider_id', 'fine_tuned', 'status', 'output_token_limit', 'modalities', 'endpoints', 'features' ];
		$placeholders = [];
		$values = [];
		$model_names = [];

		foreach ( $models_data as $model_name => $model ) {
			$placeholders[] = '(%s, %s, %s, %d, %d, %d, %s, %s, %s)';
			$values[] = $model['label'];
			$values[] = $model['name'];
			$values[] = $model['ai_provider_id'];
			$values[] = $model['fine_tuned'] ? 1 : 0;
			$values[] = $model['status'];
			$values[] = $model['output_token_limit'] ?? 0;
			$values[] = is_array( $model['modalities'] ) ? json_encode( $model['modalities'] ) : $model['modalities'];
			$values[] = is_array( $model['endpoints'] ) ? json_encode( $model['endpoints'] ) : $model['endpoints'];
			$values[] = is_array( $model['features'] ) ? json_encode( $model['features'] ) : $model['features'];

			$model_names[] = $model['name'];
		}

		$sql = "INSERT INTO `{$table_name}` (`" . implode( '`, `', $columns ) . "`) VALUES " . implode( ', ', $placeholders );

		$result = $wpdb->query( $wpdb->prepare( $sql, $values ) );

		if ( $result === false ) {
			throw new Exception( sprintf( __( 'Error on bulk insert models: %s', 'limb-chatbot' ), $wpdb->last_error ) );
		}

		// Fetch the inserted models by their names to get correct IDs
		// This is more reliable than assuming sequential IDs
		$name_placeholders = implode( ', ', array_fill( 0, count( $model_names ), '%s' ) );
		$fetch_sql = "SELECT id, name FROM `{$table_name}` WHERE name IN ({$name_placeholders}) AND ai_provider_id = %s";
		$fetch_values = array_merge( $model_names, [ Open_Router::$id ] );

		$inserted_rows = $wpdb->get_results( $wpdb->prepare( $fetch_sql, $fetch_values ), ARRAY_A );

		// Map model names to their IDs
		$inserted_ids = [];
		foreach ( $inserted_rows as $row ) {
			$inserted_ids[ $row['name'] ] = (int) $row['id'];
		}

		return $inserted_ids;
	}

	/**
	 * Bulk insert AI model metas into database.
	 *
	 * @param array $metas_data   Associative array of model_name => metas_array.
	 * @param array $inserted_ids Associative array of model_name => model_id.
	 * @return void
	 * @throws Exception
	 * @since 1.0.14
	 */
	protected function bulk_insert_ai_model_metas( array $metas_data, array $inserted_ids ): void {
		global $wpdb;

		if ( empty( $metas_data ) || empty( $inserted_ids ) ) {
			$this->log( 'No metas to insert or no model IDs available', 'warning' );
			return;
		}

		$table_name = $wpdb->prefix . AI_Model_Meta::TABLE_NAME;

		// Build the INSERT query
		$columns = [ 'ai_model_id', 'meta_key', 'meta_value' ];
		$placeholders = [];
		$values = [];
		$meta_count = 0;

		foreach ( $metas_data as $model_name => $metas ) {
			if ( ! isset( $inserted_ids[ $model_name ] ) ) {
				Helper::log( sprintf( 'No ID found for model: %s, skipping metas', $model_name ), 'warning' );
				continue;
			}

			$model_id = $inserted_ids[ $model_name ];

			foreach ( $metas as $meta_key => $meta_value ) {
				$placeholders[] = '(%d, %s, %s)';
				$values[] = $model_id;
				$values[] = $meta_key;
				$values[] = is_array( $meta_value ) || is_object( $meta_value ) ? json_encode( $meta_value ) : (string) $meta_value;
				$meta_count++;
			}
		}

		if ( empty( $placeholders ) ) {
			Helper::log( 'No meta placeholders generated', 'warning' );
			return;
		}

		$sql = "INSERT INTO `{$table_name}` (`" . implode( '`, `', $columns ) . "`) VALUES " . implode( ', ', $placeholders );

		$result = $wpdb->query( $wpdb->prepare( $sql, $values ) );

		if ( $result === false ) {
			throw new Exception( sprintf( __( 'Error on bulk insert metas: %s', 'limb-chatbot' ), $wpdb->last_error ) );
		}
	}

	/**
	 * Update an existing model with new data.
	 *
	 * @param AI_Model $existing_model The existing model to update.
	 * @param array    $model_attributes New model attributes.
	 * @param array    $metas New meta values.
	 * @return void
	 * @since 1.0.14
	 */
	protected function update_existing_model( AI_Model $existing_model, array $model_attributes, array $metas ): void {
		// Update model attributes
		foreach ( $model_attributes as $key => $value ) {
			$existing_model->{$key} = $value;
		}
		$existing_model->save();

		// Update metas one-by-one
		foreach ( $metas as $meta_key => $meta_value ) {
			$existing_model->update_meta( $meta_key, $meta_value );
		}
	}

	/**
	 * Seeds a single model into the database.
	 *
	 * @deprecated Use bulk_insert_models or process_models_with_existing instead.
	 *
	 * Handles model variants:
	 * - For :free variants, costs are set to 0
	 * - For paid models, costs are stored and also saved as paid_* metas
	 *
	 * @param object $model_data Model data from API.
	 * @return void
	 * @since 1.0.14
	 */
	protected function seed_model( $model_data ): void {
		$model_name = $this->filter_service->get_model_name( $model_data );

		if ( empty( $model_name ) ) {
			return;
		}

		// Check if model already exists
		$existing_model = AI_Model::find_by_name( $model_name );

		$prepared = $this->prepare_model_data( $model_data );

		if ( empty( $prepared['model'] ) ) {
			return;
		}

		$model_attributes = $prepared['model'];
		$metas            = $prepared['metas'];

		if ( $existing_model ) {
			$this->update_existing_model( $existing_model, $model_attributes, $metas );
		} else {
			// Create new model - metas need to be added separately
			$created = AI_Model::create( $model_attributes );

			if ( $created instanceof AI_Model ) {
				foreach ( $metas as $meta_key => $meta_value ) {
					$created->add_meta( $meta_key, $meta_value );
				}
			}
		}
	}

	/**
	 * Seeds embedding models manually.
	 *
	 * Embedding models require manual seeding because the OpenRouter API
	 * does not provide dimension information which is required for embeddings.
	 *
	 * @return void
	 * @since 1.0.14
	 */
	protected function seed_embedding_models(): void {
		$embedding_models = $this->get_embedding_models();

		foreach ( $embedding_models as $model ) {
			$metas = $model['metas'];
			unset( $model['metas'] );

			$existing_model = AI_Model::find_by_name( $model['name'] );

			if ( $existing_model ) {
				foreach ( $model as $key => $value ) {
					$existing_model->{$key} = $value;
				}
				$existing_model->save();

				foreach ( $metas as $meta_key => $meta_value ) {
					$existing_model->update_meta( $meta_key, $meta_value );
				}
			} else {
				$created = AI_Model::create( $model );

				if ( $created instanceof AI_Model ) {
					foreach ( $metas as $meta_key => $meta_value ) {
						$created->add_meta( $meta_key, $meta_value );
					}
				}
			}
		}
	}

	/**
	 * Returns the list of embedding models with their configurations.
	 *
	 * Model dimensions are sourced from official documentation:
	 * - OpenAI: text-embedding-3-large (3072), text-embedding-3-small (1536), ada-002 (1536)
	 * - Mistral: mistral-embed (1024), codestral-embed (1024)
	 * - Google: gemini-embedding-001 (768)
	 * - Qwen: qwen3-embedding-8b (4096), qwen3-embedding-4b (2048)
	 * - Intfloat: multilingual-e5-large (1024)
	 *
	 * @return array Array of embedding model configurations.
	 * @since 1.0.14
	 */
	protected function get_embedding_models(): array {
		return [
			// OpenAI Embedding Models
			[
				'label'              => 'OpenAI: Text Embedding 3 Large',
				'name'               => 'openai/text-embedding-3-large',
				'description'        => 'Best quality',
				'ai_provider_id'     => Open_Router::$id,
				'fine_tuned'         => false,
				'status'             => AI_Model::STATUS_ACTIVE,
				'output_token_limit' => 0,
				'input_token_limit'  => 8192,
				'modalities'         => [
					'text'  => true,
					'image' => false,
					'audio' => false,
					'file'  => false,
					'video' => false,
				],
				'endpoints'          => [
					'chat_completions'  => false,
					'responses'         => false,
					'realtime'          => false,
					'embeddings'        => [
						'dimensions'    => [ 3072, 1536, 1024, 512, 256 ],
						'max_dimension' => 3072,
					],
					'speech_generation' => false,
					'transcription'     => false,
					'image_generation'  => false,
					'batch'             => false,
					'translation'       => false,
					'assistants'        => false,
					'fine_tuning'       => false,
					'moderation'        => false,
				],
				'features'           => [
					'streaming'           => false,
					'structured_outputs'  => false,
					'response_format'     => false,
					'function_calling'    => false,
					'parallel_tool_calls' => false,
					'reasoning'           => false,
					'web_search'          => false,
					'logprobs'            => false,
					'seed'                => false,
					'distillation'        => false,
					'fine_tuning'         => false,
					'predicted_outputs'   => false,
				],
				'metas'              => [
					'input_token_cost' => 0.00000013,
					'context_length'   => 8192,
					'default_dimension' => 1536,
				],
			],
			[
				'label'              => 'OpenAI: Text Embedding 3 Small',
				'name'               => 'openai/text-embedding-3-small',
				'description'        => 'Cheapest',
				'ai_provider_id'     => Open_Router::$id,
				'fine_tuned'         => false,
				'status'             => AI_Model::STATUS_ACTIVE,
				'output_token_limit' => 0,
				'input_token_limit'  => 8192,
				'modalities'         => [
					'text'  => true,
					'image' => false,
					'audio' => false,
					'file'  => false,
					'video' => false,
				],
				'endpoints'          => [
					'chat_completions'  => false,
					'responses'         => false,
					'realtime'          => false,
					'embeddings'        => [
						'dimensions'    => [ 1536, 1024, 512, 256 ],
						'max_dimension' => 1536,
					],
					'speech_generation' => false,
					'transcription'     => false,
					'image_generation'  => false,
					'batch'             => false,
					'translation'       => false,
					'assistants'        => false,
					'fine_tuning'       => false,
					'moderation'        => false,
				],
				'features'           => [
					'streaming'           => false,
					'structured_outputs'  => false,
					'response_format'     => false,
					'function_calling'    => false,
					'parallel_tool_calls' => false,
					'reasoning'           => false,
					'web_search'          => false,
					'logprobs'            => false,
					'seed'                => false,
					'distillation'        => false,
					'fine_tuning'         => false,
					'predicted_outputs'   => false,
				],
				'metas'              => [
					'input_token_cost' => 0.00000002,
					'context_length'   => 8192,
					'default_dimension' => 1536,
				],
			],
			[
				'label'              => 'OpenAI: Text Embedding Ada 002',
				'name'               => 'openai/text-embedding-ada-002',
				'description'        => 'Cheapest',
				'ai_provider_id'     => Open_Router::$id,
				'fine_tuned'         => false,
				'status'             => AI_Model::STATUS_ACTIVE,
				'output_token_limit' => 0,
				'input_token_limit'  => 8192,
				'modalities'         => [
					'text'  => true,
					'image' => false,
					'audio' => false,
					'file'  => false,
					'video' => false,
				],
				'endpoints'          => [
					'chat_completions'  => false,
					'responses'         => false,
					'realtime'          => false,
					'embeddings'        => [
						'dimensions' => [ 1536 ],
					],
					'speech_generation' => false,
					'transcription'     => false,
					'image_generation'  => false,
					'batch'             => false,
					'translation'       => false,
					'assistants'        => false,
					'fine_tuning'       => false,
					'moderation'        => false,
				],
				'features'           => [
					'streaming'           => false,
					'structured_outputs'  => false,
					'response_format'     => false,
					'function_calling'    => false,
					'parallel_tool_calls' => false,
					'reasoning'           => false,
					'web_search'          => false,
					'logprobs'            => false,
					'seed'                => false,
					'distillation'        => false,
					'fine_tuning'         => false,
					'predicted_outputs'   => false,
				],
				'metas'              => [
					'input_token_cost' => 0.0000001,
					'context_length'   => 8192,
					'default_dimension' => 1536,
				],
			],

			// Mistral Embedding Models
			[
				'label'              => 'Mistral: Mistral Embed 2312',
				'name'               => 'mistralai/mistral-embed-2312',
				'description'        => 'Multilingual',
				'ai_provider_id'     => Open_Router::$id,
				'fine_tuned'         => false,
				'status'             => AI_Model::STATUS_ACTIVE,
				'output_token_limit' => 0,
				'input_token_limit'  => 8192,
				'modalities'         => [
					'text'  => true,
					'image' => false,
					'audio' => false,
					'file'  => false,
					'video' => false,
				],
				'endpoints'          => [
					'chat_completions'  => false,
					'responses'         => false,
					'realtime'          => false,
					'embeddings'        => [
						'dimensions'    => [ 1024 ],
						'max_dimension' => 1024,
					],
					'speech_generation' => false,
					'transcription'     => false,
					'image_generation'  => false,
					'batch'             => false,
					'translation'       => false,
					'assistants'        => false,
					'fine_tuning'       => false,
					'moderation'        => false,
				],
				'features'           => [
					'streaming'           => false,
					'structured_outputs'  => false,
					'response_format'     => false,
					'function_calling'    => false,
					'parallel_tool_calls' => false,
					'reasoning'           => false,
					'web_search'          => false,
					'logprobs'            => false,
					'seed'                => false,
					'distillation'        => false,
					'fine_tuning'         => false,
					'predicted_outputs'   => false,
				],
				'metas'              => [
					'input_token_cost' => 0.0000001,
					'context_length'   => 8192,
					'default_dimension' => 1024,
				],
			],
			[
				'label'              => 'Mistral: Codestral Embed 2505',
				'name'               => 'mistralai/codestral-embed-2505',
				'description'        => 'For code search',
				'ai_provider_id'     => Open_Router::$id,
				'fine_tuned'         => false,
				'status'             => AI_Model::STATUS_ACTIVE,
				'output_token_limit' => 0,
				'input_token_limit'  => 8192,
				'modalities'         => [
					'text'  => true,
					'image' => false,
					'audio' => false,
					'file'  => false,
					'video' => false,
				],
				'endpoints'          => [
					'chat_completions'  => false,
					'responses'         => false,
					'realtime'          => false,
					'embeddings'        => [
						'dimensions'    => [ 1536 ],
						'max_dimension' => 1536,
					],
					'speech_generation' => false,
					'transcription'     => false,
					'image_generation'  => false,
					'batch'             => false,
					'translation'       => false,
					'assistants'        => false,
					'fine_tuning'       => false,
					'moderation'        => false,
				],
				'features'           => [
					'streaming'           => false,
					'structured_outputs'  => false,
					'response_format'     => false,
					'function_calling'    => false,
					'parallel_tool_calls' => false,
					'reasoning'           => false,
					'web_search'          => false,
					'logprobs'            => false,
					'seed'                => false,
					'distillation'        => false,
					'fine_tuning'         => false,
					'predicted_outputs'   => false,
				],
				'metas'              => [
					'input_token_cost' => 0.00000015,
					'context_length'   => 8192,
					'default_dimension' => 1024,
				],
			],

			// Google Embedding Model
			[
				'label'              => 'Google: Gemini Embedding 001',
				'name'               => 'google/gemini-embedding-001',
				'description'        => 'For knowledge base',
				'ai_provider_id'     => Open_Router::$id,
				'fine_tuned'         => false,
				'status'             => AI_Model::STATUS_ACTIVE,
				'output_token_limit' => 0,
				'input_token_limit'  => 20000,
				'modalities'         => [
					'text'  => true,
					'image' => false,
					'audio' => false,
					'file'  => false,
					'video' => false,
				],
				'endpoints'          => [
					'chat_completions'  => false,
					'responses'         => false,
					'realtime'          => false,
					'embeddings'        => [
						'dimensions' => [ 3072, 1536, 768 ],
					],
					'speech_generation' => false,
					'transcription'     => false,
					'image_generation'  => false,
					'batch'             => false,
					'translation'       => false,
					'assistants'        => false,
					'fine_tuning'       => false,
					'moderation'        => false,
				],
				'features'           => [
					'streaming'           => false,
					'structured_outputs'  => false,
					'response_format'     => false,
					'function_calling'    => false,
					'parallel_tool_calls' => false,
					'reasoning'           => false,
					'web_search'          => false,
					'logprobs'            => false,
					'seed'                => false,
					'distillation'        => false,
					'fine_tuning'         => false,
					'predicted_outputs'   => false,
				],
				'metas'              => [
					'input_token_cost' => 0.00000015,
					'context_length'   => 20000,
					'default_dimension' => 1536,
				],
			],

			// Qwen Embedding Models
			[
				'label'              => 'Qwen: Qwen3 Embedding 8B',
				'name'               => 'qwen/qwen3-embedding-8b',
				'description'        => 'Best quality',
				'ai_provider_id'     => Open_Router::$id,
				'fine_tuned'         => false,
				'status'             => AI_Model::STATUS_ACTIVE,
				'output_token_limit' => 0,
				'input_token_limit'  => 32000,
				'modalities'         => [
					'text'  => true,
					'image' => false,
					'audio' => false,
					'file'  => false,
					'video' => false,
				],
				'endpoints'          => [
					'chat_completions'  => false,
					'responses'         => false,
					'realtime'          => false,
					'embeddings'        => [
						'dimensions'    => [ 4096, 2048, 1024, 512 ],
						'max_dimension' => 4096,
					],
					'speech_generation' => false,
					'transcription'     => false,
					'image_generation'  => false,
					'batch'             => false,
					'translation'       => false,
					'assistants'        => false,
					'fine_tuning'       => false,
					'moderation'        => false,
				],
				'features'           => [
					'streaming'           => false,
					'structured_outputs'  => false,
					'response_format'     => false,
					'function_calling'    => false,
					'parallel_tool_calls' => false,
					'reasoning'           => false,
					'web_search'          => false,
					'logprobs'            => false,
					'seed'                => false,
					'distillation'        => false,
					'fine_tuning'         => false,
					'predicted_outputs'   => false,
				],
				'metas'              => [
					'input_token_cost' => 0.00000001,
					'context_length'   => 32000,
					'default_dimension' => 2048,
				],
			],
			[
				'label'              => 'Qwen: Qwen3 Embedding 4B',
				'name'               => 'qwen/qwen3-embedding-4b',
				'description'        => 'Cheapest',
				'ai_provider_id'     => Open_Router::$id,
				'fine_tuned'         => false,
				'status'             => AI_Model::STATUS_ACTIVE,
				'output_token_limit' => 0,
				'input_token_limit'  => 32768,
				'modalities'         => [
					'text'  => true,
					'image' => false,
					'audio' => false,
					'file'  => false,
					'video' => false,
				],
				'endpoints'          => [
					'chat_completions'  => false,
					'responses'         => false,
					'realtime'          => false,
					'embeddings'        => [
						'dimensions'    => [ 2560, 2048, 1024, 512 ],
						'max_dimension' => 2560,
					],
					'speech_generation' => false,
					'transcription'     => false,
					'image_generation'  => false,
					'batch'             => false,
					'translation'       => false,
					'assistants'        => false,
					'fine_tuning'       => false,
					'moderation'        => false,
				],
				'features'           => [
					'streaming'           => false,
					'structured_outputs'  => false,
					'response_format'     => false,
					'function_calling'    => false,
					'parallel_tool_calls' => false,
					'reasoning'           => false,
					'web_search'          => false,
					'logprobs'            => false,
					'seed'                => false,
					'distillation'        => false,
					'fine_tuning'         => false,
					'predicted_outputs'   => false,
				],
				'metas'              => [
					'input_token_cost' => 0.00000002,
					'context_length'   => 32768,
					'default_dimension' => 2560,
				],
			],

			// BAAI Embedding Models
			[
				'label'              => 'BAAI: bge-m3',
				'name'               => 'baai/bge-m3',
				'description'        => 'Multilingual',
				'ai_provider_id'     => Open_Router::$id,
				'fine_tuned'         => false,
				'status'             => AI_Model::STATUS_ACTIVE,
				'output_token_limit' => 0,
				'input_token_limit'  => 8192,
				'modalities'         => [
					'text'  => true,
					'image' => false,
					'audio' => false,
					'file'  => false,
					'video' => false,
				],
				'endpoints'          => [
					'chat_completions'  => false,
					'responses'         => false,
					'realtime'          => false,
					'embeddings'        => [
						'dimensions' => [ 1024 ],
					],
					'speech_generation' => false,
					'transcription'     => false,
					'image_generation'  => false,
					'batch'             => false,
					'translation'       => false,
					'assistants'        => false,
					'fine_tuning'       => false,
					'moderation'        => false,
				],
				'features'           => [
					'streaming'           => false,
					'structured_outputs'  => false,
					'response_format'     => false,
					'function_calling'    => false,
					'parallel_tool_calls' => false,
					'reasoning'           => false,
					'web_search'          => false,
					'logprobs'            => false,
					'seed'                => false,
					'distillation'        => false,
					'fine_tuning'         => false,
					'predicted_outputs'   => false,
				],
				'metas'              => [
					'input_token_cost' => 0.00000001,
					'context_length'   => 8192,
					'default_dimension' => 1024,
				],
			],

			// Intfloat Embedding Models
			[
				'label'              => 'Intfloat: Multilingual-E5-Large',
				'name'               => 'intfloat/multilingual-e5-large',
				'description'        => 'Multilingual',
				'ai_provider_id'     => Open_Router::$id,
				'fine_tuned'         => false,
				'status'             => AI_Model::STATUS_ACTIVE,
				'output_token_limit' => 0,
				'input_token_limit'  => 512,
				'modalities'         => [
					'text'  => true,
					'image' => false,
					'audio' => false,
					'file'  => false,
					'video' => false,
				],
				'endpoints'          => [
					'chat_completions'  => false,
					'responses'         => false,
					'realtime'          => false,
					'embeddings'        => [
						'dimensions' => [ 1024 ],
					],
					'speech_generation' => false,
					'transcription'     => false,
					'image_generation'  => false,
					'batch'             => false,
					'translation'       => false,
					'assistants'        => false,
					'fine_tuning'       => false,
					'moderation'        => false,
				],
				'features'           => [
					'streaming'           => false,
					'structured_outputs'  => false,
					'response_format'     => false,
					'function_calling'    => false,
					'parallel_tool_calls' => false,
					'reasoning'           => false,
					'web_search'          => false,
					'logprobs'            => false,
					'seed'                => false,
					'distillation'        => false,
					'fine_tuning'         => false,
					'predicted_outputs'   => false,
				],
				'metas'              => [
					'input_token_cost' => 0.00000001,
					'context_length'   => 512,
					'default_dimension' => 1024,
				],
			],
		];
	}
}
