<?php

/**
 * Resolves the LLM provider and model from LolaCore user settings.
 *
 * @package LolaCore\LLM
 * @license GPL-2.0-or-later
 */

declare(strict_types=1);

namespace LolaCore\LLM;

use LolaCore\Admin\Settings;
use LolaCore\LLM\Providers\DeepSeek\DeepSeekModelSupport;
use WordPress\AiClient\AiClient;

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

/**
 * Single source of truth for `selected_model` (Settings → Model selector).
 *
 * Chat, Plugin Builder, and memory extraction all use the user's configured choice.
 * The only automatic rewrite is for retired DeepSeek API slugs still stored in the DB
 * (e.g. deepseek-reasoner → deepseek-v4-pro); an explicit deepseek-v4-flash selection
 * is passed through unchanged.
 */
final class SelectedModelResolver {

	/**
	 * @return array{provider: string, model: string}
	 *
	 * @throws \RuntimeException When no provider or text-generation model is available.
	 */
	public static function fromConfig(
		?string $selected = null,
		string $failureMessage = 'No AI provider is configured.'
	): array {
		if ($selected === null) {
			$selected = Settings::getConfig('selected_model', 'auto');
		}

		if (! is_string($selected)) {
			$selected = 'auto';
		}

		if ($selected !== 'auto' && strpos($selected, '|') !== false) {
			list($providerId, $modelId) = explode('|', $selected, 2);
			if ($providerId === 'deepseek') {
				$modelId = DeepSeekModelSupport::normalizeId($modelId);
			}

			return array(
				'provider' => $providerId,
				'model'    => $modelId,
			);
		}

		try {
			$registry     = AiClient::defaultRegistry();
			$provider_ids = $registry->getRegisteredProviderIds();

			foreach ($provider_ids as $provider_id) {
				try {
					$provider_class = $registry->getProviderClassName($provider_id);
					$model_dir      = $provider_class::modelMetadataDirectory();
					$models         = $model_dir->listModelMetadata();

					foreach ($models as $model) {
						$caps = $model->getSupportedCapabilities();
						if (empty($caps)) {
							return array(
								'provider' => $provider_id,
								'model'    => $model->getId(),
							);
						}
						foreach ($caps as $cap) {
							if (((string) $cap) === 'text_generation') {
								return array(
									'provider' => $provider_id,
									'model'    => $model->getId(),
								);
							}
						}
					}
				} catch (\Throwable $e) {
					continue;
				}
			}
		} catch (\Throwable $e) {
			// phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped -- Previous exception is chained, not rendered.
			throw new \RuntimeException( esc_html( $failureMessage ), 0, $e );
		}

		// phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
		throw new \RuntimeException( esc_html( $failureMessage ) );
	}
}
