<?php
/**
 * Shared Fluent Forms confirmation and email-notification helpers.
 *
 * @package WPAgentCompanion
 */

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

define( 'WPAGENT_FLUENT_FORMS_DELIVERY_LOCK_TTL', 60 );

/** @return \FluentForm\App\Services\Settings\SettingsService|WP_Error */
function wpagent_fluent_forms_settings_service() {
	if ( ! class_exists( 'FluentForm\\App\\Services\\Settings\\SettingsService' ) ) {
		return new WP_Error( 'wpagent_fluent_forms_settings_missing', __( 'Die native Fluent-Forms-Einstellungs-API ist nicht verfügbar.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	try {
		return new \FluentForm\App\Services\Settings\SettingsService();
	} catch ( Throwable $error ) {
		return new WP_Error( 'wpagent_fluent_forms_settings_failed', __( 'Die Fluent-Forms-Einstellungs-API konnte nicht initialisiert werden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
	}
}

/** @param mixed $value @return mixed */
function wpagent_fluent_forms_delivery_canonicalize( $value ) {
	if ( ! is_array( $value ) ) {
		return $value;
	}
	if ( ! array_is_list( $value ) ) {
		ksort( $value, SORT_STRING );
	}
	foreach ( $value as $key => $item ) {
		$value[ $key ] = wpagent_fluent_forms_delivery_canonicalize( $item );
	}
	return $value;
}

/** @param mixed $value */
function wpagent_fluent_forms_delivery_hash( $value ): string {
	$encoded = wp_json_encode( wpagent_fluent_forms_delivery_canonicalize( $value ), JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE );
	return hash( 'sha256', false === $encoded ? '' : $encoded );
}

/** @param mixed $value @return array<string,mixed> */
function wpagent_fluent_forms_delivery_array( $value ): array {
	if ( is_array( $value ) ) {
		return $value;
	}
	if ( is_string( $value ) ) {
		$decoded = json_decode( $value, true );
		return is_array( $decoded ) ? $decoded : array();
	}
	return array();
}

/** @param array<string,mixed> $value @return array<string,mixed> */
function wpagent_fluent_forms_confirmation_payload( array $value ): array {
	$redirect_map = array( 'samePage' => 'same_page', 'customUrl' => 'custom_url', 'customPage' => 'custom_page' );
	$redirect_to  = (string) ( $value['redirectTo'] ?? 'samePage' );
	return array(
		'redirect_to'        => $redirect_map[ $redirect_to ] ?? 'same_page',
		'message'            => wp_kses_post( (string) ( $value['messageToShow'] ?? '' ) ),
		'same_page_behavior' => in_array( $value['samePageFormBehavior'] ?? '', array( 'hide_form', 'reset_form' ), true ) ? $value['samePageFormBehavior'] : 'hide_form',
		'custom_page_id'     => absint( $value['customPage'] ?? 0 ),
		'custom_url'         => esc_url_raw( (string) ( $value['customUrl'] ?? '' ) ),
		'redirect_message'   => wp_kses_post( (string) ( $value['redirectMessage'] ?? '' ) ),
		'enable_query_string' => 'yes' === ( $value['enable_query_string'] ?? '' ),
		'query_strings'      => sanitize_text_field( (string) ( $value['query_strings'] ?? '' ) ),
	);
}

/** @param mixed $row @return array{id:int,value:array<string,mixed>} */
function wpagent_fluent_forms_notification_record( $row ): array {
	if ( is_array( $row ) ) {
		return array( 'id' => absint( $row['id'] ?? 0 ), 'value' => wpagent_fluent_forms_delivery_array( $row['value'] ?? array() ) );
	}
	return array(
		'id'    => is_object( $row ) ? absint( $row->id ?? 0 ) : 0,
		'value' => is_object( $row ) ? wpagent_fluent_forms_delivery_array( $row->value ?? array() ) : array(),
	);
}

/** @param array{id:int,value:array<string,mixed>} $record @return array<string,mixed> */
function wpagent_fluent_forms_notification_payload( array $record ): array {
	$value   = $record['value'];
	$send_to = wpagent_fluent_forms_delivery_array( $value['sendTo'] ?? array() );
	$payload = array(
		'id'             => $record['id'],
		'name'           => sanitize_text_field( (string) ( $value['name'] ?? '' ) ),
		'enabled'        => rest_sanitize_boolean( $value['enabled'] ?? false ),
		'send_to'        => array(
			'type'  => in_array( $send_to['type'] ?? '', array( 'email', 'field' ), true ) ? $send_to['type'] : 'email',
			'email' => sanitize_text_field( (string) ( $send_to['email'] ?? '' ) ),
			'field' => sanitize_text_field( (string) ( $send_to['field'] ?? '' ) ),
		),
		'from_name'      => sanitize_text_field( (string) ( $value['fromName'] ?? '' ) ),
		'from_email'     => sanitize_text_field( (string) ( $value['fromEmail'] ?? '' ) ),
		'reply_to'       => sanitize_text_field( (string) ( $value['replyTo'] ?? '' ) ),
		'bcc'            => sanitize_text_field( (string) ( $value['bcc'] ?? '' ) ),
		'subject'        => sanitize_text_field( (string) ( $value['subject'] ?? '' ) ),
		'message'        => wp_kses_post( (string) ( $value['message'] ?? '' ) ),
		'email_template' => sanitize_key( (string) ( $value['email_template'] ?? '' ) ),
	);
	$payload['hash'] = wpagent_fluent_forms_delivery_hash( $payload );
	return $payload;
}

/**
 * @param array{service:object,form:mixed} $authorized
 * @return array<string,mixed>|WP_Error
 */
function wpagent_fluent_forms_delivery_snapshot( array $authorized ) {
	$form_id  = absint( wpagent_fluent_forms_model_array( $authorized['form'] )['id'] ?? 0 );
	$settings = wpagent_fluent_forms_settings_service();
	if ( is_wp_error( $settings ) ) {
		return $settings;
	}
	try {
		$general = $settings->general( $form_id );
		$rows    = $settings->get( array( 'form_id' => $form_id, 'meta_key' => 'notifications' ) );
	} catch ( Throwable $error ) {
		return new WP_Error( 'wpagent_fluent_forms_delivery_read_failed', __( 'Bestätigung und E-Mail-Benachrichtigungen konnten nicht gelesen werden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
	}
	$general = is_array( $general ) ? $general : array();
	$form_settings = wpagent_fluent_forms_delivery_array( $general['generalSettings'] ?? array() );
	$advanced = wpagent_fluent_forms_delivery_array( $general['advancedValidationSettings'] ?? array() );
	$confirmation = wpagent_fluent_forms_confirmation_payload( wpagent_fluent_forms_delivery_array( $form_settings['confirmation'] ?? array() ) );
	$records = array();
	foreach ( is_iterable( $rows ) ? $rows : array() as $row ) {
		$record = wpagent_fluent_forms_notification_record( $row );
		if ( $record['id'] > 0 ) {
			$records[ $record['id'] ] = $record;
		}
		if ( count( $records ) > 500 ) {
			return new WP_Error( 'wpagent_fluent_forms_delivery_too_large', __( 'Das Formular enthält mehr als 500 E-Mail-Benachrichtigungen und wird aus Sicherheitsgründen nicht bearbeitet.', 'wp-agent-companion' ), array( 'status' => 409 ) );
		}
	}
	ksort( $records, SORT_NUMERIC );
	$notifications = array_map( 'wpagent_fluent_forms_notification_payload', array_values( $records ) );
	$raw_hash      = wpagent_fluent_forms_delivery_hash( array( $form_settings, $advanced, $records ) );
	return array(
		'form_id'           => $form_id,
		'service'           => $settings,
		'form_settings'     => $form_settings,
		'advanced_settings' => $advanced,
		'confirmation'      => $confirmation,
		'confirmation_hash' => wpagent_fluent_forms_delivery_hash( array( $form_settings, $advanced ) ),
		'notification_records' => $records,
		'notifications'     => $notifications,
		'notifications_hash' => wpagent_fluent_forms_delivery_hash( $records ),
		'raw_hash'          => $raw_hash,
		'state_hash'        => wpagent_fluent_forms_delivery_hash(
			array(
				'form_state_hash' => wpagent_fluent_forms_full_state_hash( $authorized['form'] ),
				'delivery_hash'   => $raw_hash,
			)
		),
	);
}

/** @param array<string,mixed> $notification @return array<string,mixed> */
function wpagent_fluent_forms_notification_compact( array $notification ): array {
	$send_to = wpagent_fluent_forms_delivery_array( $notification['send_to'] ?? array() );
	return array(
		'id'      => absint( $notification['id'] ?? 0 ),
		'name'    => sanitize_text_field( (string) ( $notification['name'] ?? '' ) ),
		'enabled' => rest_sanitize_boolean( $notification['enabled'] ?? false ),
		'send_to' => array( 'type' => in_array( $send_to['type'] ?? '', array( 'email', 'field' ), true ) ? $send_to['type'] : 'email' ),
		'subject' => sanitize_text_field( (string) ( $notification['subject'] ?? '' ) ),
		'hash'    => (string) ( $notification['hash'] ?? '' ),
	);
}

/** @param array<string,mixed> $snapshot @return array<string,mixed> */
function wpagent_fluent_forms_delivery_public( array $snapshot, bool $include_notification_details = false ): array {
	$notifications = is_array( $snapshot['notifications'] ?? null ) ? $snapshot['notifications'] : array();
	if ( ! $include_notification_details ) {
		$notifications = array_map( 'wpagent_fluent_forms_notification_compact', $notifications );
	}
	return array(
		'form_id'            => absint( $snapshot['form_id'] ?? 0 ),
		'confirmation'       => $snapshot['confirmation'] ?? array(),
		'confirmation_hash'  => (string) ( $snapshot['confirmation_hash'] ?? '' ),
		'notifications'      => $notifications,
		'notifications_hash' => (string) ( $snapshot['notifications_hash'] ?? '' ),
		'state_hash'         => (string) ( $snapshot['state_hash'] ?? '' ),
		'notification_details_included' => $include_notification_details,
	);
}

/** @return array<string,mixed>|WP_Error */
function wpagent_fluent_forms_delivery_state( int $form_id ) {
	$authorized = wpagent_fluent_forms_get_authorized_form( array( 'form_id' => $form_id ) );
	return is_wp_error( $authorized ) ? $authorized : wpagent_fluent_forms_delivery_snapshot( $authorized );
}

/** @return string|WP_Error */
function wpagent_fluent_forms_delivery_expected_hash( $value ) {
	$hash = is_string( $value ) ? strtolower( $value ) : '';
	return preg_match( '/^[a-f0-9]{64}$/', $hash ) ? $hash : new WP_Error( 'wpagent_fluent_forms_delivery_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_delivery_acquire_lock( int $form_id ) {
	$option = 'wp_agent_fluent_delivery_lock_' . $form_id;
	$token  = wpagent_companion_acquire_option_lock( $option, WPAGENT_FLUENT_FORMS_DELIVERY_LOCK_TTL );
	if ( is_string( $token ) ) {
		return $token;
	}
	return new WP_Error( 'wpagent_fluent_forms_delivery_busy', __( 'Die Zustellungsoptionen dieses Formulars werden gerade geändert. Versuche es gleich erneut.', 'wp-agent-companion' ), array( 'status' => 409 ) );
}

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

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