<?php
/**
 * Seguridad: nonces, sanitización y escape.
 */

final class JB_Security {
	private static $nonces = array();

	public static function create_nonce( $action ) {
		$token = bin2hex( random_bytes( 16 ) );
		if ( ! isset( $_SESSION['jb_nonces'] ) ) {
			$_SESSION['jb_nonces'] = array();
		}
		if ( ! isset( $_SESSION['jb_nonces'][ $action ] ) || ! is_array( $_SESSION['jb_nonces'][ $action ] ) ) {
			$_SESSION['jb_nonces'][ $action ] = array();
		}
		$_SESSION['jb_nonces'][ $action ][] = $token;
		if ( count( $_SESSION['jb_nonces'][ $action ] ) > 12 ) {
			$_SESSION['jb_nonces'][ $action ] = array_slice( $_SESSION['jb_nonces'][ $action ], -12 );
		}
		return $token;
	}

	public static function verify_nonce( $nonce, $action ) {
		if ( empty( $_SESSION['jb_nonces'][ $action ] ) ) {
			return false;
		}
		$stored = (array) $_SESSION['jb_nonces'][ $action ];
		foreach ( $stored as $token ) {
			if ( hash_equals( (string) $token, (string) $nonce ) ) {
				return true;
			}
		}
		return false;
	}
}

function wp_create_nonce( $action = -1 ) {
	return JB_Security::create_nonce( (string) $action );
}

function wp_verify_nonce( $nonce, $action = -1 ) {
	return JB_Security::verify_nonce( (string) $nonce, (string) $action ) ? 1 : false;
}

function check_ajax_referer( $action, $query_arg = false, $die = true ) {
	$nonce = '';
	if ( false === $query_arg ) {
		$nonce = $_REQUEST['_ajax_nonce'] ?? $_REQUEST['nonce'] ?? '';
	} else {
		$nonce = $_REQUEST[ $query_arg ] ?? '';
	}
	if ( ! wp_verify_nonce( $nonce, $action ) ) {
		if ( $die ) {
			if ( ! is_user_logged_in() ) {
				wp_send_json_error(
					array(
						'message' => 'Sesión expirada. Vuelve a iniciar sesión.',
						'code'    => 'session_expired',
					),
					401
				);
			}
			wp_send_json_error(
				array(
					'message' => 'Token de seguridad inválido. Recarga la página.',
					'code'    => 'nonce_invalid',
				),
				403
			);
		}
		return false;
	}
	return true;
}

function check_admin_referer( $action, $query_arg = '_wpnonce' ) {
	$nonce = $_REQUEST[ $query_arg ] ?? $_POST[ $query_arg ] ?? '';
	if ( ! wp_verify_nonce( $nonce, $action ) ) {
		wp_die( 'Enlace de seguridad no válido. Recarga la página e intenta de nuevo.' );
	}
}

function wp_unslash( $value ) {
	if ( is_array( $value ) ) {
		return array_map( 'wp_unslash', $value );
	}
	return stripslashes( $value );
}

function sanitize_text_field( $str ) {
	$str = wp_unslash( $str );
	$str = strip_tags( $str );
	return trim( preg_replace( '/[\r\n\t ]+/', ' ', $str ) );
}

function sanitize_textarea_field( $str ) {
	if ( is_array( $str ) || is_object( $str ) ) {
		return '';
	}
	$str = wp_unslash( (string) $str );
	$str = strip_tags( $str );
	$str = str_replace( array( "\0", "\r\n", "\r" ), array( '', "\n", "\n" ), $str );
	return trim( $str );
}

function sanitize_html_class( $classname, $fallback = '' ) {
	$sanitized = preg_replace( '/[^A-Za-z0-9_-]/', '', (string) $classname );
	if ( '' === $sanitized && '' !== $fallback ) {
		return sanitize_html_class( $fallback );
	}
	return $sanitized;
}

function sanitize_key( $key ) {
	$key = strtolower( (string) $key );
	return preg_replace( '/[^a-z0-9_\-]/', '', $key );
}

function sanitize_title( $title ) {
	$title = strtolower( remove_accents( $title ) );
	return preg_replace( '/[^a-z0-9\-]/', '-', $title );
}

function sanitize_email( $email ) {
	return filter_var( trim( $email ), FILTER_SANITIZE_EMAIL );
}

function sanitize_user( $username, $strict = false ) {
	$username = trim( (string) $username );
	$username = preg_replace( '/\s+/', ' ', $username );
	return $strict ? preg_replace( '/[^a-zA-Z0-9 _.\-@]/', '', $username ) : strip_tags( $username );
}

function sanitize_file_name( $filename ) {
	return preg_replace( '/[^a-zA-Z0-9._\-]/', '', $filename );
}

function esc_html( $text ) {
	return htmlspecialchars( (string) $text, ENT_QUOTES, 'UTF-8' );
}

function esc_attr( $text ) {
	return esc_html( $text );
}

function esc_url( $url ) {
	return filter_var( $url, FILTER_SANITIZE_URL );
}

function esc_url_raw( $url ) {
	return esc_url( $url );
}

function esc_js( $text ) {
	return htmlspecialchars( (string) $text, ENT_QUOTES, 'UTF-8' );
}

function esc_textarea( $text ) {
	return esc_html( $text );
}

function wp_kses_post( $data ) {
	$allowed = '<p><br><strong><em><ul><ol><li><a><h1><h2><h3><h4><h5><h6><table><thead><tbody><tr><th><td><img><span><div>';
	return strip_tags( $data, $allowed );
}

function absint( $maybeint ) {
	return abs( (int) $maybeint );
}

function remove_accents( $string ) {
	$unwanted = array(
		'á'=>'a','é'=>'e','í'=>'i','ó'=>'o','ú'=>'u','ñ'=>'n',
		'Á'=>'A','É'=>'E','Í'=>'I','Ó'=>'O','Ú'=>'U','Ñ'=>'N',
	);
	return strtr( $string, $unwanted );
}

function wp_die( $message = '', $title = '', $args = array() ) {
	if ( wp_doing_ajax() ) {
		wp_send_json_error( array( 'message' => wp_strip_all_tags( $message ) ) );
	}

	// Compatible con WordPress: wp_die( $msg, 403 ) o wp_die( $msg, '', array( 'response' => 403 ) ).
	if ( is_int( $title ) || ( is_numeric( $title ) && '' !== (string) $title ) ) {
		$args     = is_array( $args ) ? $args : array();
		$args['response'] = (int) $title;
		$title    = '';
	}
	if ( ! is_array( $args ) ) {
		$args = array();
	}

	$code = isset( $args['response'] ) ? (int) $args['response'] : 500;
	if ( $code < 400 || $code > 599 ) {
		$code = 500;
	}
	http_response_code( $code );

	$page_title = '' !== (string) $title ? (string) $title : (string) $code;
	echo '<!DOCTYPE html><html><head><meta charset="utf-8"><title>' . esc_html( $page_title ) . '</title></head><body>';
	echo '<h1>' . esc_html( $page_title ) . '</h1><p>' . esc_html( $message ) . '</p></body></html>';
	exit;
}

function wp_strip_all_tags( $string ) {
	return strip_tags( $string );
}

function wp_json_encode( $data, $options = 0, $depth = 512 ) {
	return json_encode( $data, $options | JSON_UNESCAPED_UNICODE, $depth );
}

function wp_slash( $value ) {
	if ( is_array( $value ) ) {
		return array_map( 'wp_slash', $value );
	}
	return addslashes( $value );
}
