<?php
/**
 * REST endpoint for form submissions.
 *
 * @package ThemeREX\AutoDealer
 */

declare(strict_types=1);

namespace ThemeREX\AutoDealer\Forms;

defined( 'ABSPATH' ) || exit;
use WP_Error;
use WP_REST_Request;
use WP_REST_Response;

class FormHandler {

	/**
	 * Register the REST route.
	 *
	 * @return void
	 */
	public function register(): void {
		add_action( 'rest_api_init', array( $this, 'registerRoutes' ) );
	}

	/**
	 * Register REST routes.
	 *
	 * @return void
	 */
	public function registerRoutes(): void {
		register_rest_route(
			TRX_AD_REST_NAMESPACE,
			'/forms/submit',
			array(
				'methods'             => 'POST',
				'callback'            => array( $this, 'handleSubmission' ),
				'permission_callback' => '__return_true',
			)
		);
	}

	/**
	 * Handle a form submission.
	 *
	 * @param WP_REST_Request $request Request object.
	 * @return WP_REST_Response|WP_Error
	 */
	public function handleSubmission( WP_REST_Request $request ): WP_REST_Response|WP_Error {
		// Honeypot check.
		$hp = $request->get_param( 'trx_ad_hp' );
		if ( ! empty( $hp ) ) {
			// Silently reject — bots fill hidden fields.
			return new WP_REST_Response(
				array(
					'success' => true,
					'message' => '',
				)
			);
		}

		// Nonce check.
		$nonce = $request->get_param( '_trx_ad_form_nonce' );
		if ( ! $nonce || ! wp_verify_nonce( $nonce, 'trx_ad_form_submit' ) ) {
			return new WP_Error(
				'invalid_nonce',
				__( 'Security check failed. Please refresh the page and try again.', 'trx-auto-dealer' ),
				array( 'status' => 403 )
			);
		}

		$formId = sanitize_key( $request->get_param( 'form_id' ) ?? '' );
		$postId = absint( $request->get_param( 'post_id' ) ?? 0 );

		$config = FormConfig::get( $formId );
		if ( ! $config ) {
			return new WP_Error(
				'invalid_form',
				__( 'Invalid form.', 'trx-auto-dealer' ),
				array( 'status' => 400 )
			);
		}

		// Extract and validate field values.
		$rawFields   = $request->get_param( 'fields' ) ?? array();
		$fieldValues = array();
		$errors      = array();

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

		foreach ( $config['fields'] as $fieldDef ) {
			$id       = $fieldDef['id'] ?? '';
			$label    = $fieldDef['label'] ?? $id;
			$type     = $fieldDef['type'] ?? 'text';
			$required = ! empty( $fieldDef['required'] );
			$value    = isset( $rawFields[ $id ] ) ? trim( (string) $rawFields[ $id ] ) : '';

			// Sanitize by type.
			switch ( $type ) {
				case 'email':
					$value = sanitize_email( $value );
					if ( $required && ( '' === $value || ! is_email( $value ) ) ) {
						$errors[] = sprintf(
							/* translators: %s: field label */
							__( '%s is not a valid email address.', 'trx-auto-dealer' ),
							$label
						);
					}
					break;

				case 'textarea':
					$value = sanitize_textarea_field( $value );
					break;

				default:
					$value = sanitize_text_field( $value );
					break;
			}

			if ( $required && '' === $value && 'email' !== $type ) {
				$errors[] = sprintf(
					/* translators: %s: field label */
					__( '%s is required.', 'trx-auto-dealer' ),
					$label
				);
			}

			$fieldValues[ $id ] = $value;
		}

		if ( ! empty( $errors ) ) {
			return new WP_Error(
				'validation_failed',
				implode( ' ', $errors ),
				array( 'status' => 422 )
			);
		}

		// Rate limiting per BUILD-ORDER §7: 3 submissions / IP / hour, scoped
		// per listing (post ID). Tracked as a counter transient with HOUR_IN_SECONDS
		// TTL — refreshed only when the counter is first set, so the window slides
		// forward on the FIRST hit and any submissions inside that hour share the cap.
		$ip      = isset( $_SERVER['REMOTE_ADDR'] ) ? sanitize_text_field( wp_unslash( (string) $_SERVER['REMOTE_ADDR'] ) ) : 'unknown';
		$rlKey   = 'trx_ad_rl_' . md5( $ip . '|' . $postId );
		$rlLimit = (int) apply_filters( 'trx_ad_form_rate_limit', 3, $formId, $postId );
		$rlCount = (int) get_transient( $rlKey );
		if ( $rlCount >= $rlLimit ) {
			return new WP_Error(
				'rate_limited',
				__( 'You have reached the submission limit for this listing. Please try again later.', 'trx-auto-dealer' ),
				array( 'status' => 429 )
			);
		}
		set_transient( $rlKey, $rlCount + 1, HOUR_IN_SECONDS );

		// Send email.
		$sent = FormMailer::send( $config, $fieldValues, $postId, $formId );

		/**
		 * Fires after a form is submitted.
		 *
		 * @param string $formId      Form ID.
		 * @param array  $fieldValues Submitted values.
		 * @param int    $postId      Listing post ID.
		 * @param bool   $sent        Whether the email was sent.
		 */
		do_action( 'trx_ad_form_submitted', $formId, $fieldValues, $postId, $sent );

		$message = $config['success_message'] ?? __( 'Thank you! Your message has been sent.', 'trx-auto-dealer' );

		return new WP_REST_Response(
			array(
				'success' => true,
				'message' => $message,
			)
		);
	}
}
