<?php
/**
 * Carteasy – RevocationHelper
 *
 * Static helpers für Widerruf nach EU-RL 2026/2673.
 * Bewusst ohne DB-State, nur Pure-Functions.
 *
 * @copyright  Wlanium / Thomas Bartelt
 * @since      2026-04-19
 */

include_once $_SERVER['DOCUMENT_ROOT'].'/core/config/revocation_config.inc.php';

class RevocationHelper {

	/**
	 * Prüft, ob eine Kundengruppe zum elektronischen Widerruf berechtigt ist.
	 */
	public static function is_b2c($customer_group_id) {
		$b2c = unserialize(REVOCATION_B2C_GROUP_IDS);
		return in_array((int)$customer_group_id, $b2c, true);
	}

	/**
	 * Liefert die customer_group_id für eine Bestellung.
	 * Bei Gast (customer_id NULL) → REVOCATION_GUEST_GROUP_ID (103).
	 * Sonst aus customer-Tabelle gezogen.
	 */
	public static function resolve_group_id($db, $customer_id) {
		if (empty($customer_id)) {
			return REVOCATION_GUEST_GROUP_ID;
		}
		$customer_id = (int)$customer_id;
		$sql = "SELECT customer_group_id FROM customers WHERE id = $customer_id LIMIT 1";
		$result = $db->query($sql);
		if ($result && $result->num_rows > 0) {
			$row = $result->fetch_object();
			return (int)$row->customer_group_id;
		}
		return 0;
	}

	/**
	 * Erzeugt ein kryptographisch zufälliges Token (Hex).
	 */
	public static function generate_token() {
		return bin2hex(random_bytes(REVOCATION_TOKEN_BYTES));
	}

	/**
	 * SHA-256 des Klartext-Tokens. Nur dieser Hash wird persistiert.
	 */
	public static function hash_token($token_plain) {
		return hash('sha256', $token_plain);
	}

	/**
	 * Baut die vollständige Widerrufs-URL für eine Bestell-Mail.
	 */
	public static function build_link($token_plain, $host = null) {
		if ($host === null) {
			$host = (isset($_SERVER['HTTP_HOST']) && $_SERVER['HTTP_HOST'])
				? $_SERVER['HTTP_HOST']
				: 'www.intelectra.de';
		}
		return 'https://' . $host . REVOCATION_LANDING_PATH
			. '?t=' . urlencode($token_plain);
	}

	/**
	 * DSGVO-konforme IP-Anonymisierung.
	 *   IPv4: letztes Oktett auf 0   (/24)
	 *   IPv6: letzte 80 Bits auf 0   (/48)
	 * Ungültige Eingabe → NULL.
	 */
	public static function anonymize_ip($ip) {
		if (empty($ip)) {
			return null;
		}
		if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
			$parts = explode('.', $ip);
			$parts[3] = '0';
			return implode('.', $parts);
		}
		if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
			$bin = inet_pton($ip);
			if ($bin === false) return null;
			// /48: erste 6 Bytes behalten, Rest auf 0
			$masked = substr($bin, 0, 6) . str_repeat("\0", 10);
			return inet_ntop($masked);
		}
		return null;
	}

	/**
	 * Berechnet den expires_at-Timestamp ab einem Basis-Datum.
	 * $base_date: 'YYYY-MM-DD' aus orders.order_date, oder null → jetzt.
	 */
	public static function calc_expires_at($base_date = null) {
		$days = (int) REVOCATION_TOKEN_VALIDITY_DAYS;
		if (!empty($base_date)) {
			$ts = strtotime($base_date);
			if ($ts === false) $ts = time();
		} else {
			$ts = time();
		}
		return date('Y-m-d H:i:s', $ts + $days * 86400);
	}
}
