<?php
/**
 * EAC Block Builder - Générateur de blocs Gutenberg en PHP pur
 * Génére automatiquement le JavaScript inline sans dépendances externes
 *
 * @since 2.5.3
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

use EACCustomWidgets\EAC_Plugin;
use EACCustomWidgets\Includes\Blocks\AcfBlockBuilder\Block_Registry;

require_once __DIR__ . '/acf-location-rules.php';
require_once __DIR__ . '/block-lib.php';
require_once __DIR__ . '/block-field.php';
require_once __DIR__ . '/block-registery.php';

add_action( 'init', 'register_eac_block', 99, 1 );
add_action( 'enqueue_block_editor_assets', 'eac_builder_enqueue_editor_assets' );

/**
 * register_eac_block
 * Fonction publique pour l'utilisateur final
 * Peut être appelée n'importe où, functions.php du thème ou mu-plugins
 *
 * @param string|array $block
 *
 * @return bool
 */
function register_eac_block( $block ): bool {
	$block_name = '';
	$block_data = '';

	if ( ! is_array( $block ) || empty( $block ) || ( ! isset( $block['path'] ) && ! isset( $block['name'] ) ) ) {
		/**error_log( 'Invalid block configuration: "block_path" and "block_name" are required.' ); // phpcs:ignore*/
		return false;
	}

	if ( ! is_readable( $block['path'] ) && ! is_dir( $block['path'] ) ) {
		error_log( sprintf( '%s: %s', esc_attr( $block_name ?? 'unknown' ), esc_html__( 'The block path is not found or is unreadable.', 'eac-components' ) ) ); // phpcs:ignore
		return false;
	}

	$block_name = trim( sanitize_text_field( $block['name'] ) );
	$block_data = eac_register_block_type( $block );

	if ( empty( $block_data ) ) {
		return false;
	}

	// Le bloc est enregistré dans eac_register_block_type, mais on doit vérifier s'il est enregistré dans le registre de WordPress
	if ( WP_Block_Type_Registry::get_instance()->is_registered( $block_name ) ) {
		// Ajouter à la liste existante, pas remplacer
		$managed_blocks = get_option( 'eac_options_generated_blocks', array() );

		if ( ! is_array( $managed_blocks ) ) {
			$managed_blocks = array();
		}

		// Ajouter seulement si pas déjà présent
		if ( ! in_array( $block_name, $managed_blocks, true ) ) {
			$managed_blocks[] = $block_name;
			update_option( 'eac_options_generated_blocks', $managed_blocks );
		}
	} else {
		error_log( sprintf( '%s: %s', esc_attr( $block_name ?? 'unknown' ), esc_html__( 'The block is not registered.', 'eac-components' ) ) ); // phpcs:ignore
		return false;
	}

	// Stockez chaque bloc avec sa clé unique 'block_name' dans le registre des blocs
	Block_Registry::register( $block_name, $block_data );

	if ( ! wp_script_is( 'eac-generate-block', 'registered' ) ) {
		wp_register_script(
			'eac-generate-block',
			EAC_Plugin::instance()->get_script_url( 'includes/blocks/acf-block-builder/assets/js/block' ),
			array( 'wp-blocks', 'wp-element', 'wp-block-editor', 'wp-components', 'wp-i18n', 'wp-data', 'wp-api-fetch', 'wp-server-side-render' ),
			filemtime( EAC_Plugin::instance()->get_script_path( 'includes/blocks/acf-block-builder/assets/js/block' ) ),
			true
		);
		wp_set_script_translations( 'eac-generate-block', 'eac-components', EAC_PLUGIN_PATH . 'languages' );
	}

	return true;
}

/**
 * eac_builder_enqueue_editor_assets
 * Enqueue les scripts utiles dans l'éditeur et passe les paramètres
 *
 * @return void
 */
function eac_builder_enqueue_editor_assets(): void {
	$all_registered_block = Block_Registry::get_all();

	// Passez tous les blocs accumulés en une seule fois
	if ( is_array( $all_registered_block ) && ! empty( $all_registered_block ) ) {
		wp_add_inline_script(
			'eac-generate-block',
			'window.eacBlockBuilder = ' . wp_json_encode( $all_registered_block, JSON_HEX_TAG ),
			'before'
		);
	}

	wp_enqueue_script( 'eac-generate-block' );
}

/**
 * eac_register_block_type
 * Enregistrer un bloc avec configuration PHP
 *
 * @param array $block
 *
 * @return array
 */
function eac_register_block_type( array $block ): array {
	$block_path = trim( wp_normalize_path( untrailingslashit( sanitize_text_field( $block['path'] ) ) ) );
	$block_name = trim( sanitize_text_field( $block['name'] ) );

	// Récupérer les attributs JSON
	$attr_json = get_block_attributes_from_json( $block_path, $block_name );
	if ( is_wp_error( $attr_json ) ) {
		$error_code = $attr_json->get_error_code();
		$error_message = $attr_json->get_error_message();
		error_log( sprintf( '[%s] %s', esc_html( $error_code ), esc_html( $error_message ) ) ); // phpcs:ignore
		return array();
	}

	// Récupérer les attributs ACF
	$acf_error_message = '';
	$attr_acf = get_block_attributes_from_acf( $block_name );
	if ( is_wp_error( $attr_acf ) ) {
		$acf_error_message = $attr_acf->get_error_message();
		$attr_acf = array(); // Continuer avec tableau vide mais avec message d'erreur qui sera affiché dans la sidebar de l'éditeur
	}

	// Fusionner les attributs ACF & JSON
	$attributes = array_merge( $attr_acf, $attr_json );


	// Un seul enregistrement avec tous les attributs
	$registered = register_block_type_from_metadata( $block_path, array(
		'attributes' => $attributes,
	) );

	// Vérifier que l'enregistrement a réussi
	if ( is_wp_error( $registered ) ) {
		error_log( sprintf( '%s "%s" : %s', esc_html__( 'Block registration error', 'eac-components' ), esc_attr( $block_name ), esc_html( $registered->get_error_message() ) ) ); // phpcs:ignore
		return array();
	}

	return array(
		'attributes' => $attributes,
		'acf_error'  => $acf_error_message,
	);
}

/**
 * get_block_attributes_from_json
 * Récupère les attributs du bloc à partir du fichier JSON
 *
 * @param string $block_path Chemin du répertoire du bloc.
 * @param string $block_name Nom du bloc.
 * @return array|WP_Error Attributs du bloc ou erreur
 */
function get_block_attributes_from_json( string $block_path, string $block_name ) {
	$attributes = array();
	$json_path  = sprintf( '%s/block.json', $block_path );

	if ( ! file_exists( $json_path ) ) {
		return new WP_Error( 'json_file', esc_html__( 'JSON file not found', 'eac-components' ) );
	}

	$json_content = @wp_json_file_decode( $json_path, array( 'associative' => true ) ); // phpcs:ignore WordPress.PHP.NoSilencedErrors

	if ( is_null( $json_content ) ) {
		return new WP_Error( 'json_file', esc_html__( 'The JSON file is malformed', 'eac-components' ) );
	}

	if ( ! isset( $json_content['name'] ) || $block_name !== $json_content['name'] ) {
		return new WP_Error( 'json_file', esc_html__( 'Different block name', 'eac-components' ) );
	}

	if ( ! isset( $json_content['render'] ) || empty( $json_content['render'] ) ) {
		return new WP_Error( 'json_file', esc_html__( 'Render is not defined', 'eac-components' ) );
	}

	// Gère pas les attributs du fichier JSON, mais on peut les récupérer pour les utiliser dans l'éditeur
	/**$attributs = isset( $json_content['attributes'] ) ? $json_content['attributes'] : array();*/

	// Appel la fonction pour générer les attributs des supports.
	$additional_attributes = get_standard_supports_attributes();

	/**$attributes = array_merge( $attributs, $additional_attributes );*/

	return $additional_attributes;
}

/**
 * get_standard_supports_attributes
 * Retourne des attributs à partir des supports Gutenberg
 * Ces attributs sont utilisés pour la compatibilité avec les fonctionnalités de l'éditeur Gutenberg
 * Ils ne génèrent pas de controles dans l'éditeur, mais permettent de gérer les styles
 * Les attributs sont définis dans le fichier block.json du bloc, mais ils peuvent être orphelins si le bloc est managé par EAC Block Builder
 * Ils seront supprimés par la synchonisation avec le filtre render_block_data (block-lib.php) si le bloc est managé par EAC Block Builder
 * Bon ce n'est pas très clair pour moi aussi, mais c'est comme ça que ça fonctionne. Je ne suis pas sûr de ce que je fais, mais je fais de mon mieux.
 *
 * @return array
 */
function get_standard_supports_attributes(): array {
	return array(
		// Alignement du bloc
		'align'           => array( 'type' => 'string' ),

		// Couleur (racine)
		'backgroundColor' => array( 'type' => 'string' ),
		'textColor'       => array( 'type' => 'string' ),
		'linkColor'       => array( 'type' => 'string' ),
		'gradient'        => array( 'type' => 'string' ),
		'borderColor'     => array( 'type' => 'string' ),

		// Typographie (racine)
		'fontSize'        => array( 'type' => 'string' ),
		'fontFamily'      => array( 'type' => 'string' ),
		'fontWeight'      => array( 'type' => 'string' ),
		'letterSpacing'   => array( 'type' => 'string' ),
		'textTransform'   => array( 'type' => 'string' ),
		'fontStyle'       => array( 'type' => 'string' ),

		// Objet style (imbriqué)
		'style'           => array(
			'type' => 'object',
			'additionalProperties' => true,
		),
	);
}
