<?php
/**
 * PS_Label_Consent_Gate — backend gate. Wszystkie endpointy etykiety MUSZĄ wywołać
 * require_consent_or_fail() PRZED jakąkolwiek operacją (Oracle, Furgonetka, dispatch, etc.).
 *
 * Polityka: SPEC/11_CONSENT_AND_TERMS.md sekcja 4.
 * Single Responsibility: TYLKO walidacja stanu zgody. NIE pisze, NIE renderuje.
 *
 * @package ParcelSelectorFree
 */

defined( 'ABSPATH' ) || exit;

final class Parcselect_Label_Consent_Gate {

	public static function init() {}

	/**
	 * Sprawdza czy zgoda jest aktualna (wersja terms + md5 zgodne z bieżącymi).
	 *
	 * @return true|WP_Error true = OK, WP_Error gdy missing/expired/version-mismatch.
	 */
	public static function require_consent_or_fail() {
		if ( ! class_exists( 'Parcselect_Label_Consent_Log' ) || ! class_exists( 'Parcselect_Label_Terms' ) ) {
			return new WP_Error(
				'consent_module_missing',
				'Consent modules not loaded',
				array( 'status' => 500 )
			);
		}

		$log = Parcselect_Label_Consent_Log::read_main();
		if ( null === $log || empty( $log['first_acceptance'] ) ) {
			return new WP_Error(
				'no_consent',
				'Consent never given for this installation',
				array( 'status' => 403, 'gate' => 'consent_required' )
			);
		}

		$accepted_version = isset( $log['first_acceptance']['terms_version'] )
			? (string) $log['first_acceptance']['terms_version'] : '';
		$accepted_md5 = isset( $log['first_acceptance']['terms_md5'] )
			? (string) $log['first_acceptance']['terms_md5'] : '';

		$current_version = Parcselect_Label_Terms::version();
		$current_md5     = Parcselect_Label_Terms::canonical_md5();

		if ( $accepted_version !== $current_version || $accepted_md5 !== $current_md5 ) {
			// Sprawdź history — może już renew dla bieżącej wersji.
			$history = isset( $log['history'] ) && is_array( $log['history'] ) ? $log['history'] : array();
			$renewed = false;
			foreach ( array_reverse( $history ) as $h ) {
				$hv  = isset( $h['version'] ) ? (string) $h['version'] : '';
				$hm5 = isset( $h['md5'] ) ? (string) $h['md5'] : '';
				if ( $hv === $current_version && $hm5 === $current_md5 ) {
					$renewed = true;
					break;
				}
			}
			if ( ! $renewed ) {
				return new WP_Error(
					'terms_version_mismatch',
					'Terms updated; consent required again',
					array( 'status' => 403, 'gate' => 'consent_required', 'new_version' => $current_version )
				);
			}
		}

		return true;
	}

	/**
	 * Zwraca true gdy zgoda jest aktualna — bez WP_Error (do warunków render).
	 *
	 * @return bool
	 */
	public static function is_valid() {
		$r = self::require_consent_or_fail();
		return ( true === $r );
	}

	/**
	 * Zapisz per-order snapshot przed użyciem (każde create_session).
	 * Wywoływać PO require_consent_or_fail() i PRZED faktyczną operacją.
	 *
	 * @param int    $order_id
	 * @param string $pi_id
	 * @return void
	 */
	public static function record_per_order_use( $order_id, $pi_id = '' ) {
		if ( ! class_exists( 'Parcselect_Label_Consent_Log' ) ) {
			return;
		}
		Parcselect_Label_Consent_Log::write_per_order(
			(int) $order_id,
			(string) $pi_id,
			array(
				'wp_user_id' => get_current_user_id(),
				'remote_ip'  => isset( $_SERVER['REMOTE_ADDR'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) ) : '',
				'user_agent' => isset( $_SERVER['HTTP_USER_AGENT'] ) ? sanitize_text_field( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) ) : '',
			)
		);
	}
}
