<?php

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

class Sabriel_Crypto {

	private static function get_key( $eredita = false ) {
		if ( $eredita ) {
			$materiale = ( defined( 'AUTH_KEY' ) ? AUTH_KEY : '' ) . ( defined( 'AUTH_SALT' ) ? AUTH_SALT : '' );
			if ( ! $materiale ) {
				$materiale = 'sabriel-ai-' . home_url();
			}
		} else {
			$materiale = wp_salt( 'auth' );
		}
		return hash( 'sha256', $materiale, true );
	}

	public static function cifratura_disponibile() {
		return function_exists( 'openssl_encrypt' )
			&& function_exists( 'openssl_decrypt' )
			&& in_array( 'aes-256-cbc', openssl_get_cipher_methods(), true );
	}

	public static function encrypt( $chiaro ) {
		if ( '' === (string) $chiaro || ! function_exists( 'openssl_encrypt' ) ) {
			return (string) $chiaro;
		}

		try {
			$iv = random_bytes( 16 );
		} catch ( Exception $e ) {
			return (string) $chiaro;
		} catch ( Error $e ) {
			return (string) $chiaro;
		}
		$cifrato = openssl_encrypt( $chiaro, 'aes-256-cbc', self::get_key(), OPENSSL_RAW_DATA, $iv );
		if ( false === $cifrato ) {
			return (string) $chiaro;
		}

		return 'sabc1:' . base64_encode( $iv . $cifrato );
	}

	public static function decrypt( $valore ) {
		$valore = (string) $valore;
		if ( '' === $valore || 0 !== strpos( $valore, 'sabc1:' ) || ! function_exists( 'openssl_decrypt' ) ) {
			return $valore;
		}
		$raw = base64_decode( substr( $valore, 6 ), true );
		if ( false === $raw || strlen( $raw ) < 17 ) {
			/*
			 * ⚠ VUOTO, NON IL VALORE GREZZO. Qui si torna indietro solo per un
			 * valore che PORTA il marchio 'sabc1:' ma non si riesce a decodificare:
			 * e' un dato rovinato (troncato da un'esportazione del database o da una
			 * migrazione), non una chiave. Restituendolo com'era, chi chiama credeva
			 * di avere una chiave buona: il pannello scriveva «presente e cifrata»,
			 * il pallino rosso restava spento e il bot mandava «sabc1:...» al motore
			 * AI, che rispondeva 401 — bot muto e nessuno che dicesse perche'.
			 * ⚠ NON vale per le chiavi salvate in chiaro dalle versioni vecchie:
			 * quelle non hanno il marchio 'sabc1:' e escono intatte dalla riga sopra.
			 */
			return '';
		}
		$iv      = substr( $raw, 0, 16 );
		$cifrato = substr( $raw, 16 );
		$chiaro  = openssl_decrypt( $cifrato, 'aes-256-cbc', self::get_key(), OPENSSL_RAW_DATA, $iv );
		if ( false === $chiaro ) {
			$chiaro = openssl_decrypt( $cifrato, 'aes-256-cbc', self::get_key( true ), OPENSSL_RAW_DATA, $iv );
		}
		return false === $chiaro ? '' : $chiaro;
	}
}
