<?php
/** Safe, provider-native Fluent Forms field helpers. */

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

define( 'WPAGENT_FLUENT_FORMS_FIELDS_LOCK_TTL', 30 );

/** @return array<string,array<string,mixed>> */
function wpagent_fluent_forms_field_definitions(): array {
	return array(
		'text' => array( 'element' => 'input_text', 'template_name' => 'input_text', 'supports' => array( 'label', 'help_message', 'placeholder', 'required', 'default_value', 'max_length' ) ),
		'email' => array( 'element' => 'input_email', 'supports' => array( 'label', 'help_message', 'placeholder', 'required', 'default_value', 'max_length' ) ),
		'textarea' => array( 'element' => 'textarea', 'supports' => array( 'label', 'help_message', 'placeholder', 'required', 'default_value', 'max_length' ) ),
		'number' => array( 'element' => 'input_number', 'supports' => array( 'label', 'help_message', 'placeholder', 'required', 'default_value', 'min', 'max', 'step' ) ),
		'select' => array( 'element' => 'select', 'multiple' => false, 'supports' => array( 'label', 'help_message', 'placeholder', 'required', 'default_value', 'choices' ) ),
		'multi_select' => array( 'element' => 'select', 'multiple' => true, 'supports' => array( 'label', 'help_message', 'placeholder', 'required', 'default_values', 'choices' ) ),
		'radio' => array( 'element' => 'input_radio', 'supports' => array( 'label', 'help_message', 'required', 'default_value', 'choices' ) ),
		'checkbox' => array( 'element' => 'input_checkbox', 'supports' => array( 'label', 'help_message', 'required', 'default_values', 'choices' ) ),
		'name' => array( 'element' => 'input_name', 'supports' => array( 'label', 'subfields' ) ),
		'address' => array( 'element' => 'address', 'supports' => array( 'label', 'subfields' ) ),
		'country' => array( 'element' => 'select_country', 'supports' => array( 'label', 'help_message', 'placeholder', 'required', 'default_value' ) ),
		'url' => array( 'element' => 'input_url', 'supports' => array( 'label', 'help_message', 'placeholder', 'required', 'default_value', 'max_length' ) ),
		'date' => array( 'element' => 'input_date', 'supports' => array( 'label', 'help_message', 'placeholder', 'required', 'default_value', 'date_format', 'time_enabled' ) ),
		'phone' => array( 'element' => 'phone', 'supports' => array( 'label', 'help_message', 'placeholder', 'required', 'default_value' ) ),
		'file' => array( 'element' => 'input_file', 'supports' => array( 'label', 'help_message', 'required' ) ),
		'image' => array( 'element' => 'input_image', 'supports' => array( 'label', 'help_message', 'required' ) ),
	);
}

/** @param array<string,mixed> $component @param array<string,mixed> $definition */
function wpagent_fluent_forms_component_matches( array $component, array $definition, bool $matching_template = false ): bool {
	if ( (string) ( $component['element'] ?? '' ) !== (string) $definition['element'] ) {
		return false;
	}
	$attributes = is_array( $component['attributes'] ?? null ) ? $component['attributes'] : array();
	if ( $matching_template && isset( $definition['template_name'] ) && (string) ( $attributes['name'] ?? '' ) !== (string) $definition['template_name'] ) {
		return false;
	}
	if ( 'input_text' === (string) $definition['element'] && array_key_exists( 'data-mask', $attributes ) ) {
		return false;
	}
	if ( array_key_exists( 'multiple', $definition ) && (bool) ( $attributes['multiple'] ?? false ) !== (bool) $definition['multiple'] ) {
		return false;
	}
	return true;
}

/** @param array<string,mixed> $component */
function wpagent_fluent_forms_field_type( array $component ): string {
	foreach ( wpagent_fluent_forms_field_definitions() as $type => $definition ) {
		if ( wpagent_fluent_forms_component_matches( $component, $definition ) ) {
			return $type;
		}
	}
	return 'unsupported';
}

/** @return array{templates:array<string,array<string,mixed>>,types:array<int,array<string,mixed>>}|WP_Error */
function wpagent_fluent_forms_field_catalog( object $service, int $form_id ) {
	try {
		$groups   = $service->components( $form_id );
		$disabled = is_callable( array( $service, 'getDisabledComponents' ) ) ? $service->getDisabledComponents() : array();
	} catch ( Throwable $error ) {
		return new WP_Error( 'wpagent_fluent_forms_components_failed', __( 'Die verfügbaren Fluent-Forms-Feldtypen konnten nicht gelesen werden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
	}
	$components = array();
	foreach ( is_array( $groups ) ? $groups : array() as $group ) {
		$rows = is_array( $group['fields'] ?? null ) ? $group['fields'] : ( is_array( $group ) ? $group : array() );
		foreach ( $rows as $component ) {
			if ( is_array( $component ) && isset( $component['element'] ) ) {
				$components[] = $component;
			}
		}
	}
	$disabled  = is_array( $disabled ) ? $disabled : array();
	$templates = array();
	$types     = array();
	foreach ( wpagent_fluent_forms_field_definitions() as $type => $definition ) {
		$template = array();
		foreach ( $components as $component ) {
			if ( wpagent_fluent_forms_component_matches( $component, $definition, true ) ) {
				$template = $component;
				break;
			}
		}
		$element   = (string) $definition['element'];
		$is_blocked = ! empty( $disabled[ $element ]['disabled'] );
		$available = (bool) $template && ! $is_blocked;
		if ( $available ) {
			$templates[ $type ] = $template;
		}
		$types[] = array(
			'type'      => $type,
			'available' => $available,
			'reason'    => $available ? '' : ( $is_blocked ? 'provider_disabled' : 'provider_unavailable' ),
			'supports'  => $definition['supports'],
		);
	}
	return array( 'templates' => $templates, 'types' => $types );
}

/** @param mixed $value @return int|float|string */
function wpagent_fluent_forms_public_number( $value ) {
	if ( '' === $value || null === $value || ! is_numeric( $value ) ) {
		return '';
	}
	$number = (float) $value;
	return floor( $number ) === $number ? (int) $number : $number;
}

/** @param array<string,mixed> $field @return array<string,mixed> */
function wpagent_fluent_forms_public_subfield( array $field ): array {
	$attributes = is_array( $field['attributes'] ?? null ) ? $field['attributes'] : array();
	$settings   = is_array( $field['settings'] ?? null ) ? $field['settings'] : array();
	$required   = ! empty( $settings['validation_rules']['required']['value'] );
	return array(
		'label'        => sanitize_text_field( (string) ( $settings['label'] ?? '' ) ),
		'help_message' => sanitize_text_field( (string) ( $settings['help_message'] ?? '' ) ),
		'placeholder'  => sanitize_text_field( (string) ( $attributes['placeholder'] ?? '' ) ),
		'required'     => $required,
		'visible'      => ! array_key_exists( 'visible', $settings ) || (bool) $settings['visible'],
		'max_length'   => absint( $attributes['maxlength'] ?? 0 ),
	);
}

/** @param array<string,mixed> $field @return array<string,mixed> */
function wpagent_fluent_forms_public_field( array $field ): array {
	$attributes = is_array( $field['attributes'] ?? null ) ? $field['attributes'] : array();
	$settings   = is_array( $field['settings'] ?? null ) ? $field['settings'] : array();
	$type       = wpagent_fluent_forms_field_type( $field );
	$key        = sanitize_text_field( (string) ( $attributes['name'] ?? '' ) );
	$public     = array(
		'key'              => $key,
		'type'             => $type,
		'provider_element' => sanitize_key( (string) ( $field['element'] ?? '' ) ),
		'label'            => sanitize_text_field( (string) ( $settings['label'] ?? $settings['admin_field_label'] ?? '' ) ),
		'help_message'     => sanitize_text_field( (string) ( $settings['help_message'] ?? '' ) ),
		'placeholder'      => sanitize_text_field( (string) ( $attributes['placeholder'] ?? '' ) ),
		'required'         => ! empty( $settings['validation_rules']['required']['value'] ),
	);
	if ( 'unsupported' === $type ) {
		return $public;
	}
	if ( array_key_exists( 'value', $attributes ) ) {
		if ( is_array( $attributes['value'] ) ) {
			$public['default_values'] = array_values( array_map( 'sanitize_text_field', $attributes['value'] ) );
		} else {
			$public['default_value'] = sanitize_text_field( (string) $attributes['value'] );
		}
	}
	if ( ! empty( $attributes['maxlength'] ) ) {
		$public['max_length'] = absint( $attributes['maxlength'] );
	}
	if ( 'number' === $type ) {
		foreach ( array( 'min' => $settings['validation_rules']['min']['value'] ?? '', 'max' => $settings['validation_rules']['max']['value'] ?? '', 'step' => $settings['number_step'] ?? '' ) as $key => $value ) {
			$number = wpagent_fluent_forms_public_number( $value );
			if ( '' !== $number ) {
				$public[ $key ] = $number;
			}
		}
	}
	if ( in_array( $type, array( 'select', 'multi_select', 'radio', 'checkbox' ), true ) ) {
		$public['choices'] = array();
		foreach ( is_array( $settings['advanced_options'] ?? null ) ? $settings['advanced_options'] : array() as $choice ) {
			if ( is_array( $choice ) ) {
				$public['choices'][] = array(
					'label' => sanitize_text_field( (string) ( $choice['label'] ?? '' ) ),
					'value' => sanitize_text_field( (string) ( $choice['value'] ?? '' ) ),
				);
			}
		}
	}
	if ( in_array( $type, array( 'name', 'address' ), true ) ) {
		$public['subfields'] = array();
		foreach ( is_array( $field['fields'] ?? null ) ? $field['fields'] : array() as $subkey => $subfield ) {
			if ( is_array( $subfield ) ) {
				$public['subfields'][ sanitize_key( (string) $subkey ) ] = wpagent_fluent_forms_public_subfield( $subfield );
			}
		}
	}
	if ( 'date' === $type ) {
		$public['date_format']  = sanitize_text_field( (string) ( $settings['date_format'] ?? '' ) );
		$public['time_enabled'] = ! empty( $settings['is_time_enabled'] );
	}
	return $public;
}

/** @param array<string,mixed> $form_fields */
function wpagent_fluent_forms_fields_hash( array $form_fields ): string {
	$encoded = wp_json_encode( $form_fields );
	return hash( 'sha256', false === $encoded ? '' : $encoded );
}

function wpagent_fluent_forms_bad_fields_error(): WP_Error {
	return new WP_Error( 'wpagent_fluent_forms_bad_fields', __( 'Die gespeicherte Fluent-Forms-Feldstruktur ist ungültig.', 'wp-agent-companion' ), array( 'status' => 500 ) );
}

/** @param array{service:object,form:mixed} $authorized @param array<string,mixed>|null $catalog @return array<string,mixed>|WP_Error */
function wpagent_fluent_forms_fields_state( array $authorized, ?array $catalog = null ) {
	$form        = wpagent_fluent_forms_form_payload( $authorized['form'] );
	$form_fields = $form['form_fields'];
	if ( ! isset( $form_fields['fields'], $form_fields['submitButton'] ) || ! is_array( $form_fields['fields'] ) || ! is_array( $form_fields['submitButton'] ) ) {
		return wpagent_fluent_forms_bad_fields_error();
	}
	if ( null === $catalog ) {
		$catalog = wpagent_fluent_forms_field_catalog( $authorized['service'], $form['id'] );
		if ( is_wp_error( $catalog ) ) {
			return $catalog;
		}
	}
	$fields    = array();
	$seen_keys = array();
	foreach ( $form_fields['fields'] as $field ) {
		if ( ! is_array( $field ) || ( array_key_exists( 'attributes', $field ) && ! is_array( $field['attributes'] ) ) ) {
			return wpagent_fluent_forms_bad_fields_error();
		}
		$attributes = $field['attributes'] ?? array();
		if ( array_key_exists( 'name', $attributes ) && ! is_string( $attributes['name'] ) ) {
			return wpagent_fluent_forms_bad_fields_error();
		}
		$field_key = $attributes['name'] ?? '';
		if ( '' !== $field_key ) {
			if ( isset( $seen_keys[ $field_key ] ) ) {
				return new WP_Error( 'wpagent_fluent_forms_duplicate_field_key', __( 'Die gespeicherte Fluent-Forms-Feldstruktur enthält doppelte Feldschlüssel.', 'wp-agent-companion' ), array( 'status' => 500 ) );
			}
			$seen_keys[ $field_key ] = true;
		}
		$fields[] = wpagent_fluent_forms_public_field( $field );
	}
	$submit = $form_fields['submitButton']['settings']['button_ui']['text'] ?? '';
	return array(
		'form_id'      => $form['id'],
		'fields'       => $fields,
		'field_count'  => count( $fields ),
		'fields_hash'  => wpagent_fluent_forms_fields_hash( $form_fields ),
		'state_hash'   => wpagent_fluent_forms_full_state_hash( $authorized['form'] ),
		'empty'        => 0 === count( $fields ),
		'submit_label' => sanitize_text_field( (string) $submit ),
		'field_types'  => $catalog['types'],
	);
}

/** @return string|WP_Error */
function wpagent_fluent_forms_validate_field_key( $value ) {
	$key = is_string( $value ) ? $value : '';
	return preg_match( '/^[a-z][a-z0-9_-]{0,190}$/', $key )
		? $key
		: new WP_Error( 'wpagent_fluent_forms_field_key', __( 'field_key muss mit einem Kleinbuchstaben beginnen und darf nur Kleinbuchstaben, Zahlen, Unterstriche und Bindestriche enthalten.', 'wp-agent-companion' ), array( 'status' => 400 ) );
}

/** @return string|WP_Error */
function wpagent_fluent_forms_validate_fields_hash( $value ) {
	$hash = is_string( $value ) ? strtolower( $value ) : '';
	return preg_match( '/^[a-f0-9]{64}$/', $hash )
		? $hash
		: new WP_Error( 'wpagent_fluent_forms_fields_hash', __( 'expected_hash muss ein vollständiger SHA-256-Hash sein.', 'wp-agent-companion' ), array( 'status' => 400 ) );
}

/** @return string|WP_Error */
function wpagent_fluent_forms_fields_acquire_lock( int $form_id ) {
	if ( $form_id <= 0 ) {
		return new WP_Error( 'wpagent_bad_form_id', __( 'form_id muss eine positive Ganzzahl sein.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	$option = 'wp_agent_fluent_fields_lock_' . $form_id;
	$token  = wpagent_companion_acquire_option_lock( $option, WPAGENT_FLUENT_FORMS_FIELDS_LOCK_TTL );
	if ( is_string( $token ) ) {
		return $token;
	}
	return new WP_Error( 'wpagent_fluent_forms_fields_busy', __( 'Die Felder dieses Formulars werden gerade geändert. Versuche es gleich erneut.', 'wp-agent-companion' ), array( 'status' => 409 ) );
}

function wpagent_fluent_forms_fields_release_lock( int $form_id, string $token ): void {
	wpagent_companion_release_option_lock( 'wp_agent_fluent_fields_lock_' . $form_id, $token );
}

function wpagent_fluent_forms_fields_lock_is_owned( int $form_id, string $token ): bool {
	return $form_id > 0
		&& '' !== $token
		&& wpagent_companion_option_lock_is_owned( 'wp_agent_fluent_fields_lock_' . $form_id, $token );
}
