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

namespace Hafenstudios\Kurato\Cockpit;

defined( 'ABSPATH' ) || exit;

/**
 * Verbindungsdiagnose (Bauplan Kap. 4.6): HTTPS, Permalinks, REST-Loopback,
 * Uhrzeit-Drift (HMAC-Toleranz), Origin/Dienst-URL konfiguriert. Jede rote
 * Ampel traegt Ursache und naechsten Schritt (Flotten-Fehlerkultur).
 *
 * evaluate() ist rein und testbar; collect() sammelt die Umgebungswerte aus
 * WordPress und ruft evaluate().
 */
class Diagnostics {

	private Config $config;

	private HttpClient $http;

	/**
	 * @param Config     $config Kopplungs-Zustand.
	 * @param HttpClient $http   HTTP-Ausgang (REST-Loopback).
	 */
	public function __construct( Config $config, HttpClient $http ) {
		$this->config = $config;
		$this->http   = $http;
	}

	/**
	 * Sammelt die Umgebungswerte und wertet sie aus.
	 *
	 * @return array<int, array<string, string>>
	 */
	public function collect(): array {
		$rest_ok = $this->rest_loopback_ok();

		return self::evaluate(
			array(
				'https'       => 0 === strpos( home_url(), 'https://' ),
				'permalinks'  => (string) get_option( 'permalink_structure', '' ),
				'rest_ok'     => $rest_ok,
				'drift'       => null, // Ohne Dienst (CP2) noch nicht messbar.
				'origin'      => $this->config->origin(),
				'service_url' => $this->config->service_url(),
			)
		);
	}

	/**
	 * Reine Auswertung der Umgebungswerte in Ampel-Zeilen.
	 *
	 * @param array<string, mixed> $env https, permalinks, rest_ok, drift, origin, service_url.
	 * @return array<int, array<string, string>>
	 */
	public static function evaluate( array $env ): array {
		$checks = array();

		$checks[] = ( ! empty( $env['https'] ) )
			? self::ok( 'https', __( 'HTTPS ist aktiv.', 'kurato' ) )
			: self::fail(
				'https',
				__( 'Ihre Site laeuft nicht ueber HTTPS.', 'kurato' ),
				__( 'Aktivieren Sie ein SSL-Zertifikat (bei den meisten Hostern kostenlos). Ohne HTTPS ist eine Kopplung ausgeschlossen.', 'kurato' )
			);

		$checks[] = ( '' !== (string) ( $env['permalinks'] ?? '' ) )
			? self::ok( 'permalinks', __( 'Permalinks sind aktiv.', 'kurato' ) )
			: self::warn(
				'permalinks',
				__( 'Es sind einfache Permalinks eingestellt.', 'kurato' ),
				__( 'Stellen Sie unter Einstellungen > Permalinks eine sprechende Struktur ein (z. B. Beitragsname), damit die REST-Wege stabil bleiben.', 'kurato' )
			);

		$checks[] = ( ! empty( $env['rest_ok'] ) )
			? self::ok( 'rest', __( 'Die REST-API ist von aussen erreichbar.', 'kurato' ) )
			: self::fail(
				'rest',
				__( 'Die REST-API konnte nicht erreicht werden.', 'kurato' ),
				__( 'Ein Security-Plugin oder der Server blockiert vermutlich /wp-json. Geben Sie die Namespaces kurato/v1 und kurato-cockpit/v1 frei.', 'kurato' )
			);

		$drift = $env['drift'] ?? null;
		if ( null === $drift ) {
			$checks[] = self::info(
				'clock',
				__( 'Die Uhrzeit-Abweichung wird erst nach der Kopplung gegen den Dienst gemessen.', 'kurato' ),
				''
			);
		} elseif ( abs( (int) $drift ) > 300 ) {
			$checks[] = self::fail(
				'clock',
				__( 'Die Serveruhr weicht zu stark ab (mehr als 300 Sekunden).', 'kurato' ),
				__( 'Aktivieren Sie die Zeitsynchronisation (NTP) auf dem Server. Tickets sind sonst sofort ungueltig.', 'kurato' )
			);
		} else {
			$checks[] = self::ok( 'clock', __( 'Die Serveruhr liegt in der Toleranz.', 'kurato' ) );
		}

		$checks[] = ( '' !== (string) ( $env['origin'] ?? '' ) )
			? self::ok(
				'origin',
				sprintf(
					/* translators: %s: konfigurierte App-Origin. */
					__( 'Cockpit-App-Origin ist konfiguriert (%s).', 'kurato' ),
					(string) $env['origin']
				)
			)
			: self::fail(
				'origin',
				__( 'Es ist keine Cockpit-App-Origin konfiguriert.', 'kurato' ),
				__( 'Setzen Sie die Origin ueber den Filter kurato_cockpit_origin.', 'kurato' )
			);

		return $checks;
	}

	/**
	 * REST-Loopback: ruft die eigene REST-Basis auf und prueft die Antwort.
	 *
	 * @return bool
	 */
	private function rest_loopback_ok(): bool {
		$response = $this->http->post(
			rest_url( 'kurato-cockpit/v1' ),
			array( 'timeout' => 10 )
		);
		if ( is_wp_error( $response ) ) {
			return false;
		}
		// Jede HTTP-Antwort unter 500 beweist Erreichbarkeit (404 auf die Basis
		// ist ok - die Route existiert nur bei Pairing, die REST-API antwortet).
		return $response['status'] > 0 && $response['status'] < 500;
	}

	// --- Zeilen-Helfer ------------------------------------------------------

	/**
	 * @param string $key     Schluessel.
	 * @param string $message Meldung.
	 * @return array<string, string>
	 */
	private static function ok( string $key, string $message ): array {
		return array(
			'key'     => $key,
			'status'  => 'ok',
			'message' => $message,
			'next'    => '',
		);
	}

	/**
	 * @param string $key     Schluessel.
	 * @param string $message Meldung.
	 * @param string $next    Naechster Schritt.
	 * @return array<string, string>
	 */
	private static function warn( string $key, string $message, string $next ): array {
		return array(
			'key'     => $key,
			'status'  => 'warn',
			'message' => $message,
			'next'    => $next,
		);
	}

	/**
	 * @param string $key     Schluessel.
	 * @param string $message Meldung.
	 * @param string $next    Naechster Schritt.
	 * @return array<string, string>
	 */
	private static function fail( string $key, string $message, string $next ): array {
		return array(
			'key'     => $key,
			'status'  => 'fail',
			'message' => $message,
			'next'    => $next,
		);
	}

	/**
	 * @param string $key     Schluessel.
	 * @param string $message Meldung.
	 * @param string $next    Naechster Schritt.
	 * @return array<string, string>
	 */
	private static function info( string $key, string $message, string $next ): array {
		return array(
			'key'     => $key,
			'status'  => 'info',
			'message' => $message,
			'next'    => $next,
		);
	}
}
