<?php
/**
 * Zapier class for SureForms
 * Contains all the endpoints required for Zapier App.
 *
 * @package sureforms.
 * @since 1.2.0
 */

namespace SRFM_Pro\Inc\Pro;

use SRFM\Inc\Database\Tables\Entries;
use SRFM\Inc\Form_Submit;
use SRFM\Inc\Helper;
use SRFM_Pro\Inc\Helper as Pro_Helper;
use SRFM_Pro\Inc\Traits\Get_Instance;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

/**
 * Zapier class for SureForms
 * Contains all the endpoints required for Zapier App.
 *
 * @since 1.2.0
 */
class Zapier {
	use Get_Instance;

	/**
	 * Constructor
	 *
	 * @since 1.2.0
	 * @return void
	 */
	public function __construct() {
		add_filter( 'srfm_rest_api_endpoints', [ $this, 'register_endpoints' ] );
		add_action( 'srfm_form_submit', [ $this, 'send_data_to_zapier' ], 10, 1 );
		add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_assets' ] );
	}

	/**
	 * Enqueue block editor scripts for zapier.
	 *
	 * @since 1.2.0
	 * @return void
	 */
	public function enqueue_assets() {
		$file_prefix = defined( 'SRFM_DEBUG' ) && SRFM_DEBUG ? '' : '.min';
		$dir_name    = defined( 'SRFM_DEBUG' ) && SRFM_DEBUG ? 'unminified' : 'minified';
		$css_uri     = SRFM_PRO_URL . 'assets/css/' . $dir_name . '/package/pro/';

		// Load the frontend custom app styles.
		wp_enqueue_style( SRFM_PRO_SLUG . '-zapier', $css_uri . 'zapier' . $file_prefix . '.css', [], SRFM_PRO_VER );

		$scripts = [
			[
				'unique_file'        => 'zapierIntegration',
				'unique_handle'      => 'zapierIntegration',
				'extra_dependencies' => [],
			],
		];

		foreach ( $scripts as $script ) {

			$script_dep_path = SRFM_PRO_DIR . 'dist/package/pro/' . $script['unique_file'] . '.asset.php';
			$script_dep_data = file_exists( $script_dep_path )
				? include $script_dep_path
				: [
					'dependencies' => [],
					'version'      => SRFM_PRO_VER,
				];
			$script_dep      = array_merge( $script_dep_data['dependencies'], $script['extra_dependencies'] );

			// Scripts.
			wp_enqueue_script(
				SRFM_PRO_SLUG . '-' . $script['unique_handle'], // Handle.
				SRFM_PRO_URL . 'dist/package/pro/' . $script['unique_file'] . '.js',
				$script_dep, // Dependencies, defined above.
				$script_dep_data['version'], // SRFM_VER.
				true // Enqueue the script in the footer.
			);

			// Register script translations.
			Pro_Helper::register_script_translations( SRFM_PRO_SLUG . '-' . $script['unique_handle'] );
		}
	}

	/**
	 * Register endpoints for the zapier app.
	 *
	 * @param array<mixed> $data Array of endpoints.
	 * @since 1.2.0
	 * @return array<mixed>
	 */
	public function register_endpoints( $data ) {
		return array_merge(
			$data,
			[
				'zap-auth'          => [
					'methods'             => 'GET',
					'callback'            => [ $this, 'is_authorized_call' ],
					'permission_callback' => '__return_true',
				],
				'zap-get-all-forms' => [
					'methods'             => 'GET',
					'callback'            => [ $this, 'get_all_forms' ],
					'permission_callback' => [ $this, 'is_authorized_call' ],
				],
				'save-zap'          => [
					'methods'             => 'GET',
					'callback'            => [ $this, 'save_zap' ],
					'permission_callback' => [ $this, 'is_authorized_call' ],
				],
				'delete-zap'        => [
					'methods'             => 'GET',
					'callback'            => [ $this, 'delete_zap' ],
					'permission_callback' => [ $this, 'is_authorized_call' ],
				],
				'zap-auth-data'     => [
					'methods'             => 'GET',
					'callback'            => [ $this, 'get_zap_auth_data' ],
					'permission_callback' => [ Helper::class, 'get_items_permissions_check' ],
				],
				'latest-entry'      => [
					'methods'             => 'GET',
					'callback'            => [ $this, 'get_latest_entry' ],
					'permission_callback' => [ $this, 'is_authorized_call' ],
				],
			]
		);
	}

	/**
	 * Check if the call is authorized.
	 *
	 * @param  \WP_REST_Request $request Full details about the request.
	 * @since 1.2.0
	 * @return bool
	 */
	public function is_authorized_call( $request ) {
		// get the api key from the request header.
		$token = Helper::get_string_value( $request->get_header( 'Authorization' ) );

		// if the token is empty then return false.
		if ( empty( $token ) ) {
			return false;
		}

		// get the auth data from the database.
		$auth_data = get_option( 'srfm_zap_auth_data' );

		if ( empty( $auth_data ) || ! is_array( $auth_data ) || ! isset( $auth_data['zap_api_key'] ) || $token !== $auth_data['zap_api_key'] ) {
			return false;
		}

		return true;
	}

	/**
	 * Generate Zap Auth data
	 * and save it in the database.
	 *
	 * @since 1.2.0
	 * @return array<mixed>
	 */
	public function generate_zap_auth_data() {
		// generate a random api key of 16 characters and get the website url.
		$zap_api_key = wp_generate_password( 16, true );
		$website_url = get_site_url();

		$zap_auth_data = [
			'zap_api_key' => $zap_api_key,
			'website_url' => $website_url,
		];

		// save the auth data in the database.
		update_option(
			'srfm_zap_auth_data',
			$zap_auth_data
		);

		return $zap_auth_data;
	}

	/**
	 * This function sends the form data to
	 * zapier on every new form submission.
	 *
	 * @param array<mixed> $data Form submission data.
	 * @since 1.2.0
	 * @return void
	 */
	public function send_data_to_zapier( $data ) {
		$is_zap = get_option( 'srfm_zaps' );
		// get the form id and the form submission data.
		$submmitted_form_id   = Helper::get_string_value( $data['form_id'] );
		$form_submit_response = $data['data'];

		// add form_id, entry_id and form_name to the data.
		if ( ! is_array( $form_submit_response ) ) {
			$form_submit_response = [];
		}

		$form_submit_response['form_id']   = ! empty( $submmitted_form_id ) ? $submmitted_form_id : '';
		$form_submit_response['entry_id']  = ! empty( $data['entry_id'] ) ? $data['entry_id'] : '';
		$form_submit_response['form_name'] = get_the_title( Helper::get_integer_value( $submmitted_form_id ) );

		// loop through all the zaps and send the data to the zapier webhook.
		if ( ! empty( $is_zap ) && is_array( $is_zap ) ) {
			foreach ( $is_zap as $zap ) {

				if ( ! isset( $zap['form_id'] ) || ! isset( $zap['zap_url'] ) ) {
					continue;
				}

				// check if the form id is equal to the form id in the zap.
				if ( $submmitted_form_id === $zap['form_id'] ) {
					// get the zapier webhook url.
					$zapier_webhook = $zap['zap_url'];

					// if the zapier webhook is empty then skip this zap.
					if ( empty( $zapier_webhook ) ) {
						continue;
					}

					$form_submit_response_json = wp_json_encode( $form_submit_response );

					$response = wp_remote_post(
						$zapier_webhook,
						[
							'body'    => false !== $form_submit_response_json ? $form_submit_response_json : '',
							'headers' => [
								'Content-Type' => 'application/json',
							],
						]
					);

					if ( is_wp_error( $response ) ) {
						$error_message = $response->get_error_message();
						wp_send_json_error( 'Error sending data to Zapier: ' . $error_message );
					}
				}
			}
		}
	}

	/**
	 * Delete Zap
	 *
	 * @param  \WP_REST_Request $request Full details about the request.
	 * @since 1.2.0
	 * @return void
	 */
	public function delete_zap( $request ) {

		// from the request get the zap_id and remove it from the zaps array.
		$zap_id = Helper::get_string_value( $request->get_param( 'zap_id' ) );

		$zaps = get_option( 'srfm_zaps', [] );

		if ( empty( $zaps ) || ! is_array( $zaps ) ) {
			wp_send_json_error( 'No zaps found' );
		}

		foreach ( $zaps as $key => $zap ) {
			if ( $zap['zap_id'] === $zap_id ) {
				unset( $zaps[ $key ] );
			}
		}

		update_option( 'srfm_zaps', $zaps );

		$data = [
			'status' => 'unsubscribed',
		];

		wp_send_json_success( $data );
	}

	/**
	 * Save Zap
	 *
	 * @param  \WP_REST_Request $request Full details about the request.
	 * @since 1.2.0
	 * @return array|void
	 */
	public function save_zap( $request ) {
		$zap_data = $this->prepare_zap_data( $request );

		if ( empty( $zap_data ) && ! is_array( $zap_data ) ) {
			wp_send_json_error( 'Error saving zap' );
		}

		wp_send_json_success( [ 'status' => 'subscribed' ] );
	}

	/**
	 * Prepare Zap Data and Save to Options
	 *
	 * @param  \WP_REST_Request $request Full details about the request.
	 * @since 1.2.0
	 * @return array<mixed>
	 */
	public function prepare_zap_data( $request ) {
		$zap_id  = Helper::get_string_value( $request->get_param( 'zap_id' ) );
		$zap_url = Helper::get_string_value( $request->get_param( 'zap_url' ) );
		$form_id = Helper::get_string_value( $request->get_param( 'form_id' ) );

		$zap_data = [
			'zap_url' => $zap_url,
			'zap_id'  => $zap_id,
			'form_id' => $form_id,
		];

		$zaps = get_option( 'srfm_zaps', [] );

		if ( empty( $zaps ) || ! is_array( $zaps ) ) {
			$zaps = [];
		}

		$zaps[] = $zap_data;
		update_option( 'srfm_zaps', $zaps );

		return $zap_data;
	}

	/**
	 * Get latest entry
	 *
	 * @param  \WP_REST_Request $request Full details about the request.
	 * @since 1.2.0
	 * @return void
	 */
	public function get_latest_entry( $request ) {
		$data = $this->get_latest_entry_data( $request );
		wp_send_json( $data );
	}

	/**
	 * Get latest entry data
	 *
	 * @param  \WP_REST_Request $request Full details about the request.
	 * @since 1.2.0
	 * @return array<mixed>
	 */
	public function get_latest_entry_data( $request ) {
		$form_id = absint( $request->get_param( 'form_id' ) );

		// send the latest entry to zapier where form_id is equal to the form_id.
		$entry_ids = Entries::get_all_entry_ids_for_form( $form_id );

		if ( empty( $entry_ids ) ) {
			wp_send_json( [] );
		}

		$entry = Entries::get( $entry_ids[0]['ID'] );

		$data   = [];
		$data[] = Form_Submit::get_instance()->prepare_submission_data( $entry['form_data'] );

		// Add form_id, entry_id and form_name to the data.
		$data[0]['form_id']   = $form_id;
		$data[0]['entry_id']  = ! empty( $entry['ID'] ) ? $entry['ID'] : '';
		$data[0]['form_name'] = get_the_title( Helper::get_integer_value( $form_id ) );

		return $data;
	}

	/**
	 * Get all forms.
	 *
	 * @since 1.2.0
	 * @return array<mixed>
	 */
	public function get_all_forms_data() {
		// get all forms SRFM_FORMS_POST_TYPE.
		$forms = get_posts(
			[
				'post_type'      => SRFM_FORMS_POST_TYPE,
				'posts_per_page' => -1,
			]
		);

		return array_map(
			static function( $form ) {
				return [
					'id'   => $form->ID,
					'name' => $form->post_title,
				];
			},
			$forms
		);
	}

	/**
	 * Get all forms.
	 *
	 * @since 1.2.0
	 * @return void
	 */
	public function get_all_forms() {
		$forms = $this->get_all_forms_data();
		wp_send_json_success( $forms );
	}

	/**
	 * This function is used to get the zap auth data
	 * from the database and send it to the zapier app.
	 *
	 * @since 1.2.0
	 * @return void
	 */
	public function get_zap_auth_data() {

		$zap_auth_data = get_option( 'srfm_zap_auth_data' );

		if ( empty( $zap_auth_data ) ) {
			$zap_auth_data = $this->generate_zap_auth_data();
		}

		wp_send_json_success( $zap_auth_data );
	}

}
