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

namespace Hafenstudios\Kurato\Admin;

use Hafenstudios\Core\Ai\AiRequest;
use Hafenstudios\Core\Ai\AnthropicDriver;
use Hafenstudios\Core\Ai\OpenAiCompatDriver;
use Hafenstudios\Core\Core;
use Hafenstudios\Core\Support\Secrets;

defined( 'ABSPATH' ) || exit;

/**
 * KI-Einstellungen (Etappe H1, HANS-KI-KONZEPT Abschnitt 3). Betreiber richtet
 * hier den KI-Zugang ein: globaler Hauptschalter, Treiberwahl (BYO Anthropic,
 * BYO OpenAI-kompatibel, Hafenstudios-Proxy mit Badge "bald verfuegbar"),
 * verschluesselter Schluessel, Modell (Pflicht) und Endpunkt.
 *
 * Speicherort ist die Core-Option `hs_core_ai` (nicht die Kurato-Settings),
 * damit die Core-KI-Fassade sie flottenweit liest. API-/Lizenzschluessel werden
 * ueber Core\Support\Secrets verschluesselt gespeichert und nie im Klartext
 * angezeigt; ein leeres Feld behaelt den bestehenden Schluessel.
 *
 * Serverseitig ueber admin-post (D3), Cap hs_manage_settings, Nonces/Escaping.
 */
final class AiSettingsPage {

	public const SLUG        = 'kurato-ai';
	public const ACTION_SAVE = 'kurato_save_ai';
	public const ACTION_TEST = 'kurato_test_ai';

	public const OPTION = 'hs_core_ai';

	private const TEST_TRANSIENT = 'kurato_ai_test_result';

	/**
	 * Treiber-Optionen (Wert => Anzeigename).
	 *
	 * @return array<string, string>
	 */
	private function drivers(): array {
		return array(
			'anthropic'     => __( 'Eigener Schluessel: Anthropic', 'kurato' ),
			'openai_compat' => __( 'Eigener Schluessel: OpenAI-kompatibel', 'kurato' ),
			'proxy'         => __( 'Hafenstudios-Proxy', 'kurato' ),
		);
	}

	/**
	 * Registriert die admin-post-Handler.
	 *
	 * @return void
	 */
	public function register(): void {
		add_action( 'admin_post_' . self::ACTION_SAVE, array( $this, 'handle_save' ) );
		add_action( 'admin_post_' . self::ACTION_TEST, array( $this, 'handle_test' ) );
	}

	/**
	 * Liest die Konfiguration aus der Core-Option (immer ein Array).
	 *
	 * @return array<string, mixed>
	 */
	private function config(): array {
		$config = get_option( self::OPTION, array() );
		return is_array( $config ) ? $config : array();
	}

	/**
	 * Ist der Proxy-Endpunkt gesetzt (Dienst live)?
	 *
	 * @param array<string, mixed> $config Konfiguration.
	 * @return bool
	 */
	private function proxy_available( array $config ): bool {
		$proxy = is_array( $config['proxy'] ?? null ) ? $config['proxy'] : array();
		return '' !== (string) ( $proxy['endpoint'] ?? '' );
	}

	/**
	 * Rendert die Seite.
	 *
	 * @return void
	 */
	public function render(): void {
		if ( ! current_user_can( 'hs_manage_settings' ) ) {
			wp_die( esc_html__( 'Sie haben keine Berechtigung, die KI-Einstellungen zu aendern.', 'kurato' ) );
		}

		$config  = $this->config();
		$enabled = (bool) ( $config['enabled'] ?? false );
		$driver  = (string) ( $config['driver'] ?? 'anthropic' );
		$byo     = is_array( $config['byo'] ?? null ) ? $config['byo'] : array();
		$proxy_ok = $this->proxy_available( $config );

		echo '<div class="wrap hs-kurato-ai">';
		echo '<h1>' . esc_html__( 'KI-Einstellungen', 'kurato' ) . '</h1>';

		echo '<p class="description">' . esc_html__( 'Die KI ist ein Beifahrer: Sie schlaegt vor, versendet aber nie selbst. Ohne eingerichteten Zugang bleiben alle Funktionen der Flotte voll nutzbar.', 'kurato' ) . '</p>';

		$this->render_notice();

		echo '<form method="post" action="' . esc_url( admin_url( 'admin-post.php' ) ) . '">';
		echo '<input type="hidden" name="action" value="' . esc_attr( self::ACTION_SAVE ) . '" />';
		wp_nonce_field( self::ACTION_SAVE );

		echo '<h2>' . esc_html__( 'Hauptschalter', 'kurato' ) . '</h2>';
		echo '<table class="form-table"><tbody>';
		echo '<tr><th scope="row">' . esc_html__( 'KI-Funktionen aktivieren', 'kurato' ) . '</th><td>';
		echo '<label><input type="checkbox" name="enabled" value="1" ' . checked( $enabled, true, false ) . ' /> ';
		echo esc_html__( 'KI-gestuetzte Vorschlaege und Textentwuerfe einschalten', 'kurato' ) . '</label>';
		echo '<p class="description">' . esc_html__( 'Ist der Schalter aus, findet kein einziger KI-Aufruf statt (kein Datenversand an einen Anbieter).', 'kurato' ) . '</p>';
		echo '</td></tr>';
		echo '</tbody></table>';

		echo '<h2>' . esc_html__( 'Zugang', 'kurato' ) . '</h2>';
		echo '<table class="form-table"><tbody>';

		echo '<tr><th scope="row">' . esc_html__( 'Anbieter', 'kurato' ) . '</th><td><select name="driver">';
		foreach ( $this->drivers() as $value => $label ) {
			$suffix = '';
			if ( 'proxy' === $value && ! $proxy_ok ) {
				$suffix = ' - ' . __( 'bald verfuegbar', 'kurato' );
			}
			printf( '<option value="%1$s"%2$s>%3$s</option>', esc_attr( $value ), selected( $driver, $value, false ), esc_html( $label . $suffix ) );
		}
		echo '</select>';
		if ( ! $proxy_ok ) {
			echo ' <span class="hs-shield hs-shield--grey">' . esc_html__( 'Proxy: bald verfuegbar', 'kurato' ) . '</span>';
			echo '<p class="description">' . esc_html__( 'Der Hafenstudios-Proxy (Abrechnung ueber Ihre Lizenz, EU-Endpunkt) wird derzeit vorbereitet. Bis dahin nutzen Sie bitte einen eigenen Schluessel.', 'kurato' ) . '</p>';
		}
		echo '</td></tr>';

		$this->text_row( 'byo_model', __( 'Modell (Pflicht)', 'kurato' ), (string) ( $byo['model'] ?? '' ), 'text', __( 'Die genaue Modell-Kennung Ihres Anbieters. Ohne Modell findet kein Aufruf statt. Aktuelle Anthropic-Beispiele (Stand Juli 2026): claude-opus-4-8 (empfohlen), claude-sonnet-5 (guenstiger), claude-haiku-4-5 (am guenstigsten). Pruefen Sie die Modellliste Ihres Anbieters fuer aktuelle Kennungen.', 'kurato' ) );
		$this->text_row( 'byo_endpoint', __( 'API-Endpunkt', 'kurato' ), (string) ( $byo['endpoint'] ?? '' ), 'url', __( 'Anthropic: leer lassen fuer den Standard-Endpunkt. OpenAI-kompatibel: die vollstaendige chat/completions-URL Ihres Anbieters (Pflicht).', 'kurato' ) );
		$this->secret_row( 'byo_key', __( 'API-Schluessel', 'kurato' ), (string) ( $byo['key_encrypted'] ?? '' ) );

		echo '</tbody></table>';

		echo '<p><button type="submit" class="button button-primary">' . esc_html__( 'Einstellungen speichern', 'kurato' ) . '</button></p>';
		echo '</form>';

		$this->render_transparency( $driver );
		$this->render_test_section( $enabled );

		echo '</div>';
	}

	/**
	 * Transparenz-Block: welche Daten wohin fliessen, AVV-Hinweis.
	 *
	 * @param string $driver Aktueller Treiber.
	 * @return void
	 */
	private function render_transparency( string $driver ): void {
		echo '<h2>' . esc_html__( 'Transparenz und Datenschutz', 'kurato' ) . '</h2>';
		echo '<div class="notice notice-info inline" style="padding:8px 12px;max-width:820px;"><p>';
		echo esc_html__( 'Wenn Sie die KI nutzen, verlassen die fuer den jeweiligen Aufruf noetigen Texte (Zweck, Aufgabe, ggf. anonymisierter Kontext) Ihre WordPress-Installation und werden an den gewaehlten Anbieter uebertragen. Ganze Kontaktlisten werden nie uebertragen; wo moeglich wird pseudonymisiert (z.B. nur der Vorname).', 'kurato' );
		echo '</p><p>';
		if ( 'proxy' === $driver ) {
			echo esc_html__( 'Beim Hafenstudios-Proxy laeuft der Aufruf ueber unseren Dienst (Abrechnung und Kontingent serverseitig). Schliessen Sie mit Hafenstudios einen Auftragsverarbeitungsvertrag (AVV) ab.', 'kurato' );
		} else {
			echo esc_html__( 'Bei einem eigenen Schluessel gilt der AVV Ihres jeweiligen Anbieters. Bitte schliessen Sie diesen ab und pruefen Sie den Serverstandort.', 'kurato' );
		}
		echo '</p></div>';
	}

	/**
	 * Testaufruf-Bereich.
	 *
	 * @param bool $enabled Ist die KI eingeschaltet?
	 * @return void
	 */
	private function render_test_section( bool $enabled ): void {
		echo '<h2>' . esc_html__( 'Verbindung testen', 'kurato' ) . '</h2>';

		$result = get_transient( self::TEST_TRANSIENT );
		if ( is_array( $result ) ) {
			delete_transient( self::TEST_TRANSIENT );
			$class = ! empty( $result['ok'] ) ? 'notice-success' : 'notice-error';
			echo '<div class="notice ' . esc_attr( $class ) . ' inline" style="padding:8px 12px;max-width:820px;"><p>';
			echo esc_html( (string) ( $result['message'] ?? '' ) );
			echo '</p></div>';
		}

		if ( ! $enabled ) {
			echo '<p class="description">' . esc_html__( 'Schalten Sie die KI oben ein und speichern Sie, um einen Testaufruf durchzufuehren.', 'kurato' ) . '</p>';
			return;
		}

		echo '<form method="post" action="' . esc_url( admin_url( 'admin-post.php' ) ) . '">';
		echo '<input type="hidden" name="action" value="' . esc_attr( self::ACTION_TEST ) . '" />';
		wp_nonce_field( self::ACTION_TEST );
		echo '<p><button type="submit" class="button">' . esc_html__( 'Kurzer Testaufruf', 'kurato' ) . '</button></p>';
		echo '<p class="description">' . esc_html__( 'Sendet einen kurzen Testaufruf ueber den gespeicherten Zugang und zeigt an, ob er funktioniert.', 'kurato' ) . '</p>';
		echo '</form>';
	}

	/**
	 * Speichert die Einstellungen (admin-post).
	 *
	 * @return void
	 */
	public function handle_save(): void {
		if ( ! current_user_can( 'hs_manage_settings' ) ) {
			wp_die( esc_html__( 'Keine Berechtigung.', 'kurato' ) );
		}
		check_admin_referer( self::ACTION_SAVE );

		$config = $this->config();

		$config['enabled'] = ! empty( $_POST['enabled'] );
		$config['driver']  = $this->clean_driver( (string) wp_unslash( $_POST['driver'] ?? 'anthropic' ) );

		$byo = is_array( $config['byo'] ?? null ) ? $config['byo'] : array();
		$byo['provider'] = $config['driver']; // Spiegelung (Informationszweck).
		$byo['model']    = sanitize_text_field( wp_unslash( $_POST['byo_model'] ?? '' ) );
		$byo['endpoint'] = esc_url_raw( wp_unslash( $_POST['byo_endpoint'] ?? '' ) );

		// Schluessel nur ersetzen, wenn das Feld ausgefuellt ist (leer = behalten).
		$key = trim( (string) wp_unslash( $_POST['byo_key'] ?? '' ) );
		if ( '' !== $key ) {
			$byo['key_encrypted'] = Secrets::encrypt( $key );
		} elseif ( ! isset( $byo['key_encrypted'] ) ) {
			$byo['key_encrypted'] = '';
		}
		$config['byo'] = $byo;

		// Proxy-Zweig unangetastet lassen bis auf Default-Struktur.
		$proxy = is_array( $config['proxy'] ?? null ) ? $config['proxy'] : array();
		$proxy['endpoint']              = (string) ( $proxy['endpoint'] ?? '' );
		$proxy['license_key_encrypted'] = (string) ( $proxy['license_key_encrypted'] ?? '' );
		$config['proxy'] = $proxy;

		update_option( self::OPTION, $config );

		$this->redirect( 'saved' );
	}

	/**
	 * Fuehrt einen Testaufruf aus (admin-post).
	 *
	 * @return void
	 */
	public function handle_test(): void {
		if ( ! current_user_can( 'hs_manage_settings' ) ) {
			wp_die( esc_html__( 'Keine Berechtigung.', 'kurato' ) );
		}
		check_admin_referer( self::ACTION_TEST );

		$request = new AiRequest(
			'settings_test',
			__( 'Antworte mit dem Wort: OK.', 'kurato' ),
			'',
			16,
			20
		);

		$result = Core::instance()->ai()->complete( $request );

		if ( $result->ok ) {
			$message = __( 'Testaufruf erfolgreich. Der KI-Zugang funktioniert.', 'kurato' );
		} elseif ( 'disabled' === $result->error ) {
			$message = __( 'Die KI ist ausgeschaltet. Bitte aktivieren Sie den Hauptschalter.', 'kurato' );
		} else {
			$message = sprintf(
				/* translators: %s: Fehlermeldung des Anbieters */
				__( 'Testaufruf fehlgeschlagen: %s', 'kurato' ),
				$result->error
			);
		}

		set_transient( self::TEST_TRANSIENT, array( 'ok' => $result->ok, 'message' => $message ), 60 );
		$this->redirect( $result->ok ? 'test_ok' : 'test_failed' );
	}

	// --- Helfer ------------------------------------------------------------

	/**
	 * Validiert einen Treiber-Wert.
	 *
	 * @param string $value Rohwert.
	 * @return string
	 */
	private function clean_driver( string $value ): string {
		return array_key_exists( $value, $this->drivers() ) ? $value : 'anthropic';
	}

	private function render_notice(): void {
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nur Anzeige nach Redirect.
		$msg = isset( $_GET['msg'] ) ? sanitize_key( wp_unslash( $_GET['msg'] ) ) : '';
		$map = array(
			'saved'       => array( 'success', __( 'Einstellungen gespeichert.', 'kurato' ) ),
			'test_ok'     => array( 'success', __( 'Testaufruf durchgefuehrt.', 'kurato' ) ),
			'test_failed' => array( 'error', __( 'Der Testaufruf ist fehlgeschlagen. Details siehe unten.', 'kurato' ) ),
		);
		if ( isset( $map[ $msg ] ) ) {
			printf( '<div class="notice notice-%1$s is-dismissible"><p>%2$s</p></div>', esc_attr( $map[ $msg ][0] ), esc_html( $map[ $msg ][1] ) );
		}
	}

	private function text_row( string $name, string $label, string $value, string $type = 'text', string $description = '' ): void {
		echo '<tr><th scope="row"><label for="hs-' . esc_attr( $name ) . '">' . esc_html( $label ) . '</label></th>';
		echo '<td><input type="' . esc_attr( $type ) . '" id="hs-' . esc_attr( $name ) . '" name="' . esc_attr( $name ) . '" value="' . esc_attr( $value ) . '" class="regular-text" />';
		if ( '' !== $description ) {
			echo '<p class="description">' . esc_html( $description ) . '</p>';
		}
		echo '</td></tr>';
	}

	private function secret_row( string $name, string $label, string $stored ): void {
		$is_set      = '' !== $stored;
		$placeholder = $is_set ? __( 'gesetzt (leer lassen zum Behalten)', 'kurato' ) : __( 'nicht gesetzt', 'kurato' );
		echo '<tr><th scope="row"><label for="hs-' . esc_attr( $name ) . '">' . esc_html( $label ) . '</label></th>';
		echo '<td><input type="password" autocomplete="new-password" id="hs-' . esc_attr( $name ) . '" name="' . esc_attr( $name ) . '" value="" placeholder="' . esc_attr( $placeholder ) . '" class="regular-text" />';
		echo '<p class="description">' . esc_html__( 'Wird verschluesselt gespeichert und nie im Klartext angezeigt.', 'kurato' ) . '</p></td></tr>';
	}

	private function redirect( string $msg ): void {
		wp_safe_redirect( add_query_arg( array( 'page' => self::SLUG, 'msg' => $msg ), admin_url( 'admin.php' ) ) );
		exit;
	}
}
