<?php
/**
 * Retrouve un groupe de champs ACF et convertit les champs en attributs de block Gutenberg
 *
 * @since 2.5.3
 */

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

/**
 * snake_to_camel_case
 *
 * @param string $name
 * @return string
 */
function snake_to_camel_case( string $name ): string {
	return lcfirst( str_replace( ' ', '', ucwords( str_replace( '_', ' ', $name ) ) ) );
}

/**
 * get_block_attributes_from_acf
 * Récupère les attributs Gutenberg d'un groupe ACF associé à un bloc
 *
 * @param string $block_name
 * @return array|WP_Error
 */
function get_block_attributes_from_acf( string $block_name ) {
	if ( ! function_exists( 'eac_get_active_acf_block_groups' ) ) {
		return new WP_Error(
			'function_not_exists',
			esc_html__( 'ACF plugin is not active', 'eac-components' ),
			array( 'status' => 500 )
		);
	}

	$group_ids = eac_get_active_acf_block_groups( $block_name );

	if ( empty( $group_ids ) || count( $group_ids ) > 1 ) {
		return new WP_Error(
			'invalid_acf_block',
			sprintf( '%s %s', esc_html__( 'No ACF group found for', 'eac-components' ), esc_html( $block_name ) ),
			array( 'status' => 404 )
		);
	}

	$fields = acf_get_fields( reset( $group_ids ) );

	if ( ! is_array( $fields ) ) {
		return array();
	}

	return array_reduce(
		$fields,
		function ( $attributes, $field ) {
			// Validation du champ
			if ( ! is_array( $field ) || ! isset( $field['type'] ) ) {
				return $attributes;
			}

			// Ignorer les types non supportés
			if ( ! eac_block_is_supported_field_type( $field['type'] ) ) {
				return $attributes;
			}

			// Vérifier que les clés essentielles existent
			if ( ! isset( $field['name'] ) ) {
				return $attributes;
			}

			// Conversion du nom du champ ACF en camelCase pour l'attribut Gutenberg
			$field_name = snake_to_camel_case( $field['name'] );

			$attributes[ $field_name ] = eac_build_attribute_from_field( $field );
			return $attributes;
		},
		array()
	);
}

/**
 * eac_build_attribute_from_field
 * Construit un attribut Gutenberg à partir d'un champ ACF
 *
 * @param array $field
 * @return array
 */
function eac_build_attribute_from_field( array $field ): array {
	$acf_type = isset( $field['type'] ) ? $field['type'] : 'text';
	$type_map = eac_get_acf_to_gutenberg_type_map();
	$default  = eac_get_field_default( $field );

	$attributs = array(
		'type'       => $type_map[ $acf_type ] ?? 'string',
		'default'    => $default,

		// Métadonnées ACF - sans sanitization (données structurées de confiance)
		'acf_key'    => isset( $field['key'] ) ? $field['key'] : '',
		'acf_name'   => isset( $field['name'] ) ? $field['name'] : '',
		'acf_type'   => $acf_type,

		// Affichage et validation
		'label'        => isset( $field['label'] ) ? sanitize_text_field( $field['label'] ) : '',
		'instructions' => isset( $field['instructions'] ) ? sanitize_text_field( $field['instructions'] ) : '',
		'placeholder'  => isset( $field['placeholder'] ) ? sanitize_text_field( $field['placeholder'] ) : '',
		'required'     => isset( $field['required'] ) ? filter_var( $field['required'], FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE ) : false,
		'readonly'     => isset( $field['readonly'] ) ? filter_var( $field['readonly'], FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE ) : false,
		'disabled'     => isset( $field['disabled'] ) ? filter_var( $field['disabled'], FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE ) : false,
	);

	// Ajouter les propriétés conditionnelles selon le type
	$attributs = eac_add_field_specific_attributes( $attributs, $field, $acf_type );

	return $attributs;
}

/**
 * eac_add_field_specific_attributes
 * Ajoute les attributs spécifiques au type de champ
 *
 * @param array  $attributs
 * @param array  $field
 * @param string $acf_type
 * @return array
 */
function eac_add_field_specific_attributes( array $attributs, array $field, string $acf_type ): array {
	switch ( $acf_type ) {
		case 'number':
		case 'range':
			// Validation stricte des nombres
			$attributs['min']     = isset( $field['min'] ) && is_numeric( $field['min'] ) ? floatval( $field['min'] ) : null;
			$attributs['max']     = isset( $field['max'] ) && is_numeric( $field['max'] ) ? floatval( $field['max'] ) : null;
			$attributs['step']    = isset( $field['step'] ) && is_numeric( $field['step'] ) ? floatval( $field['step'] ) : 1;
			$attributs['section'] = 'settings';
			break;

		case 'text':
		case 'button_group':
			$attributs['choices']   = isset( $field['choices'] ) && is_array( $field['choices'] ) ? eac_normalize_acf_choices( $field['choices'], $field['type'] ) : array();
			$attributs['maxlength'] = isset( $field['maxlength'] ) && is_numeric( $field['maxlength'] ) ? absint( $field['maxlength'] ) : null;
			$attributs['prepend']   = isset( $field['prepend'] ) ? sanitize_text_field( $field['prepend'] ) : '';
			$attributs['append']    = isset( $field['append'] ) ? sanitize_text_field( $field['append'] ) : '';
			$attributs['section']   = 'settings';
			break;

		case 'textarea':
			$attributs['rows']      = isset( $field['rows'] ) && is_numeric( $field['rows'] ) ? absint( $field['rows'] ) : 4;
			$attributs['maxlength'] = isset( $field['maxlength'] ) && is_numeric( $field['maxlength'] ) ? absint( $field['maxlength'] ) : null;
			// Métadonnée ACF - pas de sanitization
			$attributs['new_lines'] = isset( $field['new_lines'] ) ? $field['new_lines'] : 'wpautop';
			$attributs['section']   = 'settings';
			break;

		case 'select':
			$attributs['choices']      = isset( $field['choices'] ) && is_array( $field['choices'] ) ? eac_normalize_acf_choices( $field['choices'], $field['type'] ) : array();
			$attributs['allow_null']   = isset( $field['allow_null'] ) ? filter_var( $field['allow_null'], FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE ) : false;
			$attributs['allow_custom'] = isset( $field['allow_custom'] ) ? filter_var( $field['allow_custom'], FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE ) : false;
			$attributs['multiple']     = false; /**isset( $field['multiple'] ) ? filter_var( $field['multiple'], FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE ) : false;*/
			$attributs['ui']           = isset( $field['ui'] ) ? filter_var( $field['ui'], FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE ) : false;
			$attributs['section']      = 'settings';
			break;

		case 'image':
			// Métadonnées ACF - pas de sanitization
			$attributs['library']       = isset( $field['library'] ) ? $field['library'] : 'all';
			$attributs['mime_types']    = 'image';
			$attributs['return_format'] = isset( $field['return_format'] ) ? $field['return_format'] : 'array';
			$attributs['preview_size']  = isset( $field['preview_size'] ) ? $field['preview_size'] : 'thumbnail';
			$attributs['section']       = 'image';
			break;

		case 'date_time_picker':
			$attributs['display_format'] = isset( $field['display_format'] ) ? sanitize_text_field( $field['display_format'] ) : 'Y-m-d H:i';
			$attributs['first_day']      = isset( $field['first_day'] ) && is_numeric( $field['first_day'] ) ? absint( $field['first_day'] ) : 1;
			// Métadonnée ACF - pas de sanitization
			$attributs['picker']         = isset( $field['picker'] ) ? $field['picker'] : 'date_time_picker';
			$attributs['section']        = 'date_time';
			break;

		case 'page_link':
		case 'url':
			// array_map pour nettoyer les identifiants WordPress
			$attributs['post_type'] = isset( $field['post_type'] ) && is_array( $field['post_type'] ) ? array_map( 'sanitize_key', $field['post_type'] ) : array();
			$attributs['taxonomy']  = isset( $field['taxonomy'] ) && is_array( $field['taxonomy'] ) ? array_map( 'sanitize_key', $field['taxonomy'] ) : array();
			$attributs['section']   = 'link';
			break;

		case 'true_false':
			$attributs['ui']      = isset( $field['ui'] ) ? filter_var( $field['ui'], FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE ) : false;
			$attributs['message'] = isset( $field['message'] ) ? sanitize_text_field( $field['message'] ) : '';
			$attributs['section'] = 'settings';
			break;
	}

	return $attributs;
}

/**
 * eac_get_field_default
 * Détermine la valeur par défaut d'un champ
 *
 * @param array $field
 * @return mixed
 */
function eac_get_field_default( array $field ) {
	// Pas de clé default_value = retourner valeur par défaut du type
	if ( ! isset( $field['default_value'] ) ) {
		return eac_get_type_default( $field['type'] ?? 'text' );
	}

	$default = $field['default_value'];
	$acf_type = $field['type'] ?? 'text';

	// Valider selon le type ACF
	switch ( $acf_type ) {
		case 'number':
		case 'range':
			// Gérer les strings numériques, vides, etc.
			if ( '' === $default || null === $default ) {
				return 0;
			}
			if ( ! is_numeric( $default ) ) {
				return 0;
			}
			// Garder type entier si c'est un entier
			return (float) $default === (int) $default ? (int) $default : (float) $default;

		case 'true_false':
			// Gérer bool, string, int
			if ( is_bool( $default ) ) {
				return $default;
			}
			return filter_var( $default, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE ) ?? false;

		case 'email':
			return is_email( $default ) ? sanitize_email( $default ) : '';

		case 'url':
			return esc_url_raw( $default );

		case 'textarea':
			return nl2br( esc_html( $default ) );

		case 'select':
		case 'radio':
			// Valider contre les choix disponibles
			/**if ( isset( $field['choices'] ) && is_array( $field['choices'] ) ) {
				return array_key_exists( $default, $field['choices'] ) ? $default : '';
			}*/
			return sanitize_text_field( $default );

		default:
			// Text et autres
			return is_string( $default ) ? sanitize_text_field( $default ) : '';
	}
}

/**
 * Retourner la valeur par défaut natale du type
 */
function eac_get_type_default( string $type ) {
	$defaults = array(
		'number'    => 0,
		'range'     => 0,
		'true_false' => false,
		'email'     => '',
		'url'       => '',
		'select'    => '',
		'radio'     => '',
		'textarea'  => '',
	);

	return $defaults[ $type ] ?? '';
}

/**
 * transform_acf_choices
 * transforme le champ choices en clé:valeur si un des deux éléments n'existe pas
 * @param array $choices
 * @param string $type
 *
 * @return array
 */
function eac_normalize_acf_choices( array $choices = array(), string $acf_type = 'select' ): array {
	// Valider le type ACF
	if ( ! in_array( $acf_type, array( 'select', 'button_group' ), true ) ) {
		return array();
	}

	// Mapper le type ACF vers le type de contrôle
	$type = 'button_group' === $acf_type ? 'button_group' : 'select';

	if ( ! $choices || ! is_array( $choices ) ) {
		return array();
	}

	$sanitize_slug = function ( $str ) {
		return str_replace( '-', '_', sanitize_title( $str ) );
	};

	$is_slug = function ( $str ) {
		return (bool) preg_match( '/^[a-z0-9_-]+$/', $str );
	};

	$result = array();

	foreach ( $choices as $key => $value ) {
		// Cas 1: key === value (label-only)
		if ( $key === $value ) {
			$label = $key;
			$val = $sanitize_slug( $key );
		} elseif ( 'select' === $type ) { // Cas 2: select
			$label = $value;
			$val = $sanitize_slug( $value );
		} else { // Cas 3: button_group (slug detection)
			$key_is_slug = $is_slug( $key );
			$value_is_slug = $is_slug( $value );

			if ( $key_is_slug && ! $value_is_slug ) {
				$label = $value;
				$val = $key;
			} elseif ( $value_is_slug && ! $key_is_slug ) {
				$label = $key;
				$val = $value;
			} else {
				$label = $value;
				$val = $sanitize_slug( $value );
			}
		}

		$result[] = array(
			'label' => $label,
			'value' => $val,
		);
	}

	return $result;
}

/**
 * eac_get_acf_to_gutenberg_type_map
 * Retourne la map ACF -> type Gutenberg
 *
 * @return array
 */
function eac_get_acf_to_gutenberg_type_map(): array {
	return array(
		'text'             => 'string',
		'button_group'     => 'string',
		'textarea'         => 'string',
		'number'           => 'number',
		'range'            => 'number',
		'true_false'       => 'boolean',
		'select'           => 'string',
		'date_time_picker' => 'string',
		'image'            => 'object',
		'page_link'        => 'string',
		'url'              => 'string',
	);
}

/**
 * eac_block_is_supported_field_type
 * Vérifie si un type de champ ACF est supporté
 *
 * @param string $type
 * @return bool
 */
function eac_block_is_supported_field_type( string $type ): bool {
	$map = eac_get_acf_to_gutenberg_type_map();
	return array_key_exists( $type, $map );
}
