<?php

namespace Elementor_Pay_Addons\Form\API;

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

use Elementor_Pay_Addons\Form\Form_Record;
use Elementor_Pay_Addons\Form\Form_Module;
use Elementor_Pay_Addons\Shared\Logger;

class Ajax_API_Form_Handler 
{
	public $is_success = true;
	public $messages = [
		'success' => [],
		'error' => [],
		'admin_error' => [],
	];
	public $data = [];
	public $errors = [];

	private $current_form;

	const SUCCESS = 'success';
	const ERROR = 'error';
	const FIELD_REQUIRED = 'required_field';
	const INVALID_FORM = 'invalid_form';
	const SERVER_ERROR = 'server_error';
	const SUBSCRIBER_ALREADY_EXISTS = 'subscriber_already_exists';

  public function __construct() 
  { 
    add_action( 'wp_ajax_epa_forms_customize_send_form', [ $this, 'ajax_send_form' ] );
    add_action( 'wp_ajax_nopriv_epa_forms_customize_send_form', [ $this, 'ajax_send_form' ] );
  }

  public static function is_form_submitted() {
		// PHPCS - No nonce is required, all visitors may send the form.
		return wp_doing_ajax() && isset( $_POST['action'] ) && 'epa_forms_customize_send_form' === $_POST['action']; // phpcs:ignore WordPress.Security.NonceVerification.Missing
	}

	public static function get_default_messages() {
		return [
			self::SUCCESS => esc_html__( 'Your submission was successful.', 'pay-addons-for-elementor' ),
			self::ERROR => esc_html__( 'Your submission failed because of an error.', 'pay-addons-for-elementor' ),
			self::FIELD_REQUIRED => esc_html__( 'This field is required.', 'pay-addons-for-elementor' ),
			self::INVALID_FORM => esc_html__( 'Your submission failed because the form is invalid.', 'pay-addons-for-elementor' ),
			self::SERVER_ERROR => esc_html__( 'Your submission failed because of a server error.', 'pay-addons-for-elementor' ),
			self::SUBSCRIBER_ALREADY_EXISTS => esc_html__( 'Subscriber already exists.', 'pay-addons-for-elementor' ),
		];
	}

	public static function get_default_message( $id, $settings ) {
		if ( ! empty( $settings['custom_messages'] ) ) {
			$field_id = $id . '_message';
			if ( isset( $settings[ $field_id ] ) ) {
				return $settings[ $field_id ];
			}
		}

		$default_messages = self::get_default_messages();

		return isset( $default_messages[ $id ] ) ? $default_messages[ $id ] : esc_html__( 'Unknown error.', 'pay-addons-for-elementor' );
	}

	public function ajax_send_form() {
			// Verify nonce for CSRF protection.
			if ( ! isset( $_POST['_nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['_nonce'] ) ), 'wp_rest' ) ) {
				wp_send_json_error( [
					'message' => esc_html__( 'Security verification failed. Please refresh and try again.', 'pay-addons-for-elementor' ),
				] );
			}

			$form = self::get_elementor_form();
			if ( empty( $form ) ) {
				$this
				->add_error_message( self::get_default_message( self::INVALID_FORM, [] ) )
				->send();
			}
		$this->current_form = $form;

		if ( empty( $form['settings']['form_fields'] ) ) {
			$this
				->add_error_message( self::get_default_message( self::INVALID_FORM, $form['settings'] ) )
				->send();
		}

		$record = new Form_Record( $_POST['form_fields'], $form );

		$module = Form_Module::instance();

		$action = null;
		if ( 'epa-form-redirect-action' == $form['settings']['submit_actions'] ) {
			$action = $module->actions_registrar->get( 'epa-form-redirect-action' );
		}
		if ( 'epa-form-credit-card-action' == $form['settings']['submit_actions'] ) {
			$action = $module->actions_registrar->get( 'epa-form-credit-card-action' );
		}
		if ( 'epa-form-payment-element-action' == $form['settings']['submit_actions'] ) {
			$action = $module->actions_registrar->get( 'epa-form-payment-element-action' );
		}

		if ( ! $action ) {
			$this->add_error_message('failed' . $form['settings']['submit_actions']);
			$this->add_response_data( 'form_fields',$form['settings'] );
			$this->send();
		}

		$exception = null;

		try {
			/**
			 * Filters the record before it sent to actions after submit.
			 *
			 * @since 3.3.0
			 *
			 * @param Form_Record $record The form record.
			 * @param Ajax_Handler $this The class that handle the submission of the record
			 */
			$record = apply_filters( 'elementor_pay_addons/forms/record/actions_before', $record, $this );
			$action->run_core( $record, $this );

		} catch ( \Exception $e ) {
			$exception = $e;

			// Add an admin error.
			if ( ! in_array( $exception->getMessage(), $this->messages['admin_error'], true ) ) {
				$this->add_admin_error_message( "{$action->get_label()} {$exception->getMessage()}" );
			}

			// Add a user error.
			$this->add_error_message( $this->get_default_message( self::ERROR, $this->current_form['settings'] ) );
		}
		$this->errors = array_merge( $this->messages['error'], $this->messages['admin_error'] );

		$this->send();
	}

	public static function get_elementor_form() {
		$post_data = $_POST; // phpcs:ignore WordPress.Security.NonceVerification.Missing
		// $post_id that holds the form settings.
		$post_id = $post_data['post_id'];

		// $queried_id the post for dynamic values data.
		if ( isset( $post_data['queried_id'] ) ) {
			$queried_id = $post_data['queried_id'];
		} else {
			$queried_id = $post_id;
		}

		// Make the post as global post for dynamic values.
		\Elementor\Plugin::instance()->db->switch_to_post( $queried_id );

		$form_id = $post_data['form_id'];

		$document = \Elementor\Plugin::instance()->documents->get( $post_id );
		$form = null;
		$template_id = null;

		if ( $document ) {
			$form = self::find_element_recursive( $document->get_elements_data(), $form_id );
		}

		if ( empty( $form ) ) {
			return null;
		}

		// restore default values
		$widget = \Elementor\Plugin::instance()->elements_manager->create_element_instance( $form );
		$form['settings'] = $widget->get_settings_for_display();
		$form['settings']['id'] = $form_id;
		$form['settings']['form_post_id'] = $template_id ? $template_id : $post_id;

		return $form;
	}

	public static function find_element_recursive( $elements, $form_id ) {
		foreach ( $elements as $element ) {
			if ( $form_id === $element['id'] ) {
				return $element;
			}

			if ( ! empty( $element['elements'] ) ) {
				$element = self::find_element_recursive( $element['elements'], $form_id );

				if ( $element ) {
					return $element;
				}
			}
		}

		return false;
	}

	public function add_success_message( $message ) {
		$this->messages['success'][] = $message;

		return $this;
	}

	public function add_response_data( $key, $data ) {
		$this->data[ $key ] = $data;

		return $this;
	}

	public function add_error_message( $message ) {
		$this->messages['error'][] = $message;
		$this->set_success( false );

		return $this;
	}

	public function add_error( $field, $message = '' ) {
		if ( is_array( $field ) ) {
			$this->errors += $field;
		} else {
			$this->errors[ $field ] = $message;
		}

		$this->set_success( false );

		return $this;
	}

	public function add_admin_error_message( $message ) {
		$this->messages['admin_error'][] = $message;
		$this->set_success( false );

		return $this;
	}

	public function set_success( $bool ) {
		$this->is_success = $bool;

		return $this;
	}
		public function get_current_form() {
		return $this->current_form;
	}

	public function send() {
		if ( $this->is_success ) {
			wp_send_json_success( [
				'message' => $this->get_default_message( self::SUCCESS, $this->current_form['settings'] ),
				'data' => $this->data,
			] );
		}

		if ( empty( $this->messages['error'] ) && ! empty( $this->errors ) ) {
			$this->add_error_message( $this->get_default_message( self::INVALID_FORM, $this->current_form['settings'] ) );
		}

		$post_id = $_POST['post_id'];

		$error_msg = implode( '<br>', $this->messages['error'] );
		if ( current_user_can( 'edit_post', $post_id ) && ! empty( $this->messages['admin_error'] ) ) {
			$this->add_admin_error_message( esc_html__( 'This message is not visible to site visitors.', 'pay-addons-for-elementor' ) );
			$error_msg .= '<div class="elementor-forms-admin-errors">' . implode( '<br>', $this->messages['admin_error'] ) . '</div>';
		}

		wp_send_json_error( [
			'message' => $error_msg,
			'errors' => $this->errors,
			'data' => $this->data,
		] );
	}
}
