<?php
defined('ABSPATH') || exit;

/**
 * R-LLM SEO Gateway
 */
class R_LLM_SEO_GatewayException extends RuntimeException
{
	public string $code_name = 'UNKNOWN';
	public int $http_status = 500;
	public ?string $request_id = null;
	public ?array $quota = null;

	public function set_gateway_context(
		string $code_name,
		int $http_status = 500,
		?string $request_id = null,
		?array $quota = null
	): void {
		$this->code_name   = sanitize_key($code_name);
		$this->http_status = (int)$http_status;
		$this->request_id  = is_string($request_id) ? sanitize_text_field($request_id) : null;
		$this->quota       = is_array($quota) ? $quota : null;
	}
}

function r_llm_seo_gateway_post(string $product, string $feature, array $payload): array
{
	$cfg = r_llm_seo_get_rllm_config();

	$endpoint = (string)r_llm_seo_get_gateway_endpoint();
	$endpoint = esc_url_raw($endpoint);

	$api_key = trim((string)($cfg['api_key'] ?? ''));

	$opt_site_url = '';
	if (defined('R_LLM_SEO_OPT_SITE_URL')) {
		if (function_exists('r_llm_seo_get_option')) {
			$opt_site_url = (string)r_llm_seo_get_option(R_LLM_SEO_OPT_SITE_URL, '');
		} else {
			$opt_site_url = (string)get_option(R_LLM_SEO_OPT_SITE_URL, '');
		}
	}

	$site_url = trim($opt_site_url) !== '' ? $opt_site_url : (string)site_url();
	$site_url = rtrim(esc_url_raw($site_url), '/');

	if ($endpoint === '' || $site_url === '' || $api_key === '') {
		$e = new R_LLM_SEO_GatewayException(esc_html__('設定が不足しています。', 'r-llm-seo'));
		$e->set_gateway_context('CONFIG_ERROR', 400);
		throw $e;
	}

	if (function_exists('r_llm_seo_assert_site_url_matches')) {
		r_llm_seo_assert_site_url_matches();
	}

	$body = [
		'api_key'  => $api_key,
		'site_url' => $site_url,
		'product'  => $product,
		'feature'  => $feature,
		'payload'  => $payload,
	];

	$json_body = wp_json_encode($body, JSON_UNESCAPED_UNICODE);
	if (!is_string($json_body) || $json_body === '') {
		$e = new R_LLM_SEO_GatewayException(esc_html__('リクエストデータの生成に失敗しました。', 'r-llm-seo'));
		$e->set_gateway_context('BAD_REQUEST', 400);
		throw $e;
	}

	$timeout = 25;

	$ua = 'R-LLM SEO/' . (defined('R_LLM_SEO_VERSION') ? (string)R_LLM_SEO_VERSION : '1.0.0')
		. '; WordPress/' . get_bloginfo('version')
		. '; ' . $site_url;

	$res = wp_remote_post(
		$endpoint,
		[
			'timeout'   => $timeout,
			'sslverify' => true,
			'headers'   => [
				'Content-Type' => 'application/json',
				'User-Agent'   => $ua,
			],
			'body'      => $json_body,
		]
	);

	if (is_wp_error($res)) {
		$raw_error   = (string)$res->get_error_message();
		$code_name   = 'HTTP_CLIENT_ERROR';
		$http_status = 502;

		if (stripos($raw_error, 'timed out') !== false) {
			$http_status = 504;
			$code_name   = 'UPSTREAM_TIMEOUT';
		}

		$e = new R_LLM_SEO_GatewayException(esc_html__('AIサーバーとの通信に失敗しました。時間をおいて再度お試しください。', 'r-llm-seo'));
		$e->set_gateway_context($code_name, $http_status);
		throw $e;
	}

	$http_status = (int)wp_remote_retrieve_response_code($res);
	$raw         = (string)wp_remote_retrieve_body($res);
	$data        = json_decode($raw, true);

	if (!is_array($data)) {
		$trimmed = trim($raw);
		$snippet = function_exists('mb_substr') ? mb_substr($trimmed, 0, 200) : substr($trimmed, 0, 200);
		$snippet = preg_replace('/\s+/', ' ', (string)$snippet);

		$e = new R_LLM_SEO_GatewayException(esc_html__('AIサーバーの応答を解析できませんでした。時間をおいて再度お試しください。', 'r-llm-seo'));
		$e->set_gateway_context('BAD_RESPONSE', 502);
		throw $e;
	}

	$request_id = (isset($data['request_id']) && is_string($data['request_id'])) ? $data['request_id'] : null;

	$quota = null;
	if (
		isset($data['meta']) &&
		is_array($data['meta']) &&
		isset($data['meta']['quota']) &&
		is_array($data['meta']['quota'])
	) {
		$quota = $data['meta']['quota'];
	}

	if ($quota && function_exists('r_llm_seo_quota_set_cache')) {
		r_llm_seo_quota_set_cache($quota);
	}

	if ($http_status < 200 || $http_status >= 300) {
		$code = (string)($data['code'] ?? ('HTTP_' . $http_status));

		if ($http_status === 429 && $code === 'DAILY_TOKEN_QUOTA_EXCEEDED') {
			$e = new R_LLM_SEO_GatewayException(esc_html__('本日の利用上限に達しました。', 'r-llm-seo'));
			$e->set_gateway_context($code, $http_status, $request_id, $quota);
			throw $e;
		}

		$e = new R_LLM_SEO_GatewayException(esc_html__('AIサーバーからエラーが返されました。', 'r-llm-seo'));
		$e->set_gateway_context($code, $http_status, $request_id, $quota);
		throw $e;
	}

	if (empty($data['ok'])) {
		$code = (string)($data['code'] ?? 'UNKNOWN');

		$e = new R_LLM_SEO_GatewayException(esc_html__('AIサーバーでエラーが発生しました。', 'r-llm-seo'));
		$e->set_gateway_context($code, 502, $request_id, $quota);
		throw $e;
	}

	return $data;
}