<?php
/**
 * @package Hafenstudios\Core
 */

namespace Hafenstudios\Core\Ai;

defined( 'ABSPATH' ) || exit;

/**
 * Treiber fuer den kuenftigen Hafenstudios-Proxy (HANS-KI-KONZEPT Abschnitt 3,
 * Inhaber-Entscheidung 1: BYO und Proxy ab Start). Implementiert den
 * versionierten API-Vertrag aus PROXY-API.md (v1): POST auf {base}/v1/complete,
 * Authentifizierung ueber den Lizenzschluessel-Header, Antwort mit Text,
 * Verbrauch und serverseitig gezaehltem Kontingent.
 *
 * Solange der Basis-Endpunkt leer ist (der Dienst ist noch nicht live), meldet
 * der Treiber einen DAUERHAFTEN Fehler "noch nicht verfuegbar" und macht keinen
 * HTTP-Aufruf. Die UI zeigt die Proxy-Option in diesem Zustand als
 * "bald verfuegbar" (Feature-Flag).
 */
final class ProxyDriver implements AiDriver {

	/**
	 * Header, ueber den der Lizenzschluessel uebergeben wird.
	 */
	public const LICENSE_HEADER = 'X-Hafenstudios-License';

	/**
	 * Pfad des Complete-Endpunkts, an den Basis-Endpunkt angehaengt.
	 */
	public const COMPLETE_PATH = '/v1/complete';

	private string $base_endpoint;

	private string $license_key;

	/**
	 * @param string $base_endpoint Basis-URL des Proxys (leer = noch nicht live).
	 * @param string $license_key   Lizenzschluessel (Klartext).
	 */
	public function __construct( string $base_endpoint, string $license_key ) {
		$this->base_endpoint = rtrim( $base_endpoint, '/' );
		$this->license_key   = $license_key;
	}

	/**
	 * @return string
	 */
	public function key(): string {
		return 'proxy';
	}

	/**
	 * @param AiRequest $request Der Aufruf.
	 * @return AiResult
	 */
	public function complete( AiRequest $request ): AiResult {
		if ( '' === $this->base_endpoint ) {
			return AiResult::permanent( 'Der Hafenstudios-Proxy ist noch nicht verfuegbar.' );
		}
		if ( '' === $this->license_key ) {
			return AiResult::permanent( 'Kein Lizenzschluessel hinterlegt.' );
		}

		$response = wp_remote_post(
			$this->base_endpoint . self::COMPLETE_PATH,
			array(
				'timeout' => $request->timeout,
				'headers' => array(
					self::LICENSE_HEADER => $this->license_key,
					'Content-Type'       => 'application/json',
					'Accept'             => 'application/json',
				),
				'body'    => (string) wp_json_encode(
					array(
						'purpose'    => $request->purpose,
						'system'     => $request->system,
						'prompt'     => $request->prompt,
						'max_tokens' => $request->max_tokens,
					)
				),
			)
		);

		if ( is_wp_error( $response ) ) {
			return AiResult::transient( $response->get_error_message() );
		}

		$code = (int) wp_remote_retrieve_response_code( $response );
		$body = (string) wp_remote_retrieve_body( $response );
		$json = json_decode( $body, true );
		$json = is_array( $json ) ? $json : array();

		// Erfolgsfall laut Vertrag: ok=true mit text, usage und quota.
		if ( $code >= 200 && $code < 300 && ! empty( $json['ok'] ) ) {
			$usage  = is_array( $json['usage'] ?? null ) ? $json['usage'] : array();
			$quota  = is_array( $json['quota'] ?? null ) ? $json['quota'] : array();
			$result = AiResult::success(
				(string) ( $json['text'] ?? '' ),
				isset( $usage['input'] ) ? (int) $usage['input'] : -1,
				isset( $usage['output'] ) ? (int) $usage['output'] : -1
			);
			$result->quota_used  = isset( $quota['used'] ) ? (int) $quota['used'] : -1;
			$result->quota_limit = isset( $quota['limit'] ) ? (int) $quota['limit'] : -1;
			return $result;
		}

		// Fehlerfall laut Vertrag: error.code und optional quota (bei quota_exceeded).
		$error   = is_array( $json['error'] ?? null ) ? $json['error'] : array();
		$err_code = (string) ( $error['code'] ?? '' );
		$message  = (string) ( $error['message'] ?? ( 'HTTP ' . $code ) );

		$quota       = is_array( $json['quota'] ?? null ) ? $json['quota'] : array();
		$quota_used  = isset( $quota['used'] ) ? (int) $quota['used'] : -1;
		$quota_limit = isset( $quota['limit'] ) ? (int) $quota['limit'] : -1;

		switch ( $err_code ) {
			case 'quota_exceeded':
				$result              = AiResult::permanent( '' !== $message ? $message : 'Kontingent aufgebraucht.' );
				$result->quota_used  = $quota_used;
				$result->quota_limit = $quota_limit;
				return $result;
			case 'invalid_license':
				return AiResult::permanent( '' !== $message ? $message : 'Ungueltiger Lizenzschluessel.' );
			case 'upstream_error':
				return AiResult::transient( '' !== $message ? $message : 'Der Anbieter ist voruebergehend nicht erreichbar.' );
		}

		// Unbekannter Fehler: Klassifikation nach HTTP-Status (wie BYO-Treiber).
		if ( 429 === $code || $code >= 500 ) {
			return AiResult::transient( $message );
		}
		return AiResult::permanent( $message );
	}
}
