<?php
/**
 * Zapier Addon.
 *
 * @since 2.12.0
 */

namespace Masteriyo\Addons\Zapier;

defined( 'ABSPATH' ) || exit;


use Masteriyo\Models\Webhook;
use Masteriyo\Repository\WebhookRepository;

/**
 * Zapier addon class.
 */
class ZapierAddon {

	/**
	 * The single instance of the class.
	 *
	 * @since 2.12.0
	 *
	 * @var ZapierAddon
	 */
	private static $instance = null;

	/**
	 * Constructor.
	 *
	 * @since 2.12.0
	 *
	 * @return ZapierAddon
	 */
	public static function instance() {
		if ( is_null( self::$instance ) ) {
			self::$instance = new self();
		}
		return self::$instance;
	}

	/**
	 * Constructor.
	 *
	 * @since 2.12.0
	 */
	private function __construct() {}

	/**
	 * Init.
	 *
	 * @since 2.12.0
	 * @return void
	 */
	public function init() {
		ZapierApi::instance()->init();
		add_action( 'admin_init', array( $this, 'generate_api_key' ) );
		add_action( 'masteriyo_zapier_action_get_sample', array( $this, 'get_sample' ) );
		add_action( 'masteriyo_zapier_action_subscribe', array( $this, 'subscribe' ) );
		add_action( 'masteriyo_zapier_action_unsubscribe', array( $this, 'unsubscribe' ) );
		add_filter( 'masteriyo_admin_submenus', array( $this, 'add_submenu' ) );
		add_filter( 'masteriyo_localized_admin_scripts', array( $this, 'localize_admin_scripts' ) );
		add_action( 'init', array( $this, 'register_zapier_listeners' ) );
	}

	/**
	 * Localize admin scripts.
	 *
	 * @since 2.12.0
	 * @param array $scripts
	 * @return array
	 */
	public function localize_admin_scripts( $scripts ) {
		$scripts['backend']['data']['zapier'] = array(
			'apiKey' => masteriyo_zapier_get_setting( 'api_key' ),
		);
		return $scripts;
	}

	/**
	 * Add zapier submenu.
	 *
	 * @since 2.12.0
	 * @param array $submenus
	 * @return array
	 */
	public function add_submenu( $submenus ) {
		$submenus['zapier'] = array(
			'page_title' => __( 'Zapier', 'learning-management-system' ),
			'menu_title' => __( 'Zapier', 'learning-management-system' ),
			'position'   => 73,
			'capability' => 'edit_courses',
		);
		return $submenus;
	}

	/**
	 * Generate API key.
	 *
	 * @mixin 2.12.0
	 * @return void
	 */
	public function generate_api_key() {
		Setting::read();

		$api_key = Setting::get( 'api_key' );
		if ( $api_key ) {
			return;
		}

		$api_key = masteriyo_zapier_api_hash( masteriyo_zapier_rand_hash() );

		Setting::set_props(
			array(
				'api_key' => $api_key,
				'user_id' => get_current_user_id(),
			)
		);

		Setting::save();
	}


	/**
	 * Handle zapier get sample action.
	 *
	 * @since 2.12.0
	 * @param array $data
	 * @return array
	 */
	public function get_sample( $data ) {
		$trigger = masteriyo_array_get( $data, 'trigger' );

		$response = array();
		switch ( $trigger ) {
			case 'course.completed':
				$response[] = masteriyo_zapier_get_course_completed_sample();
				break;
			case 'course.published':
				$response[] = masteriyo_zapier_get_course_sample();
				break;
			case 'lesson.published':
				$response[] = masteriyo_zapier_get_lesson_sample();
				break;
			case 'lesson.completed':
				$response[] = masteriyo_zapier_get_lesson_completed_sample();
				break;
			case 'quiz.published':
				$response[] = masteriyo_zapier_get_quiz_sample();
				break;
			case 'quiz.completed':
				$response[] = masteriyo_zapier_get_quiz_completed_sample();
				break;
			case 'quiz_attempt.status.changed':
				$response[] = masteriyo_zapier_get_quiz_attempt_sample();
				break;
			case 'student.created':
				$response[] = masteriyo_zapier_get_user_sample( 'student' );
				break;
			case 'student.enrolled':
				$response[] = masteriyo_zapier_get_user_course_sample();
				break;
			case 'course.review.created':
				$response[] = masteriyo_zapier_get_course_review_sample();
				break;
			case 'course.question.reply.created':
				$response[] = masteriyo_zapier_get_course_qa_sample( 'answer' );
				break;
			case 'course.question.created':
				$response[] = masteriyo_zapier_get_course_qa_sample();
				break;
			case 'instructor.created':
				$response[] = masteriyo_zapier_get_user_sample();
				break;
		}

		masteriyo_zapier_send_response( array_filter( $response ) );
	}


	/**
	 * Handle zapier hook subscription.
	 *
	 * @since 2.12.0
	 * @param array $data
	 * @return void
	 */
	public function subscribe( $data ) {
		$hook_url      = masteriyo_array_get( $data, 'hookUrl' );
		$trigger       = masteriyo_array_get( $data, 'trigger', '' );
		$subscriptions = masteriyo_zapier_get_setting( 'subscriptions', array() );

		if ( ! isset( $subscriptions[ $hook_url ] ) ) {
			$subscriptions[ $hook_url ] = array();
		}

		$subscriptions[ $hook_url ][] = $trigger;
		masteriyo_zapier_update_setting( 'subscriptions', $subscriptions );
	}

	/**
	 * handler zapier hook unsubscribe.
	 *
	 * @since 2.12.0
	 * @param array $data
	 * @return void
	 */
	public function unsubscribe( $data ) {
		$subscriptions = masteriyo_zapier_get_setting( 'subscriptions', array() );
		$hook_url      = masteriyo_array_get( $data, 'hookUrl', '' );
		unset( $subscriptions[ $hook_url ] );
		masteriyo_zapier_update_setting( 'subscriptions', $subscriptions );
	}

	/**
	 * Register zapier listeners.
	 *
	 * @since 2.12.0
	 * @return void
	 */
	public function register_zapier_listeners() {
		$listeners     = masteriyo_get_webhook_listeners();
		$subscriptions = masteriyo_zapier_get_setting( 'subscriptions', array() );
		$user_id       = masteriyo_zapier_get_setting( 'user_id' );

		foreach ( $subscriptions as $hook_url => $events ) {
			foreach ( $events as $event ) {
				$listener = $listeners[ $event ] ?? false;

				if ( ! $listener ) {
					continue;
				}

				$webhook = new Webhook( new WebhookRepository() );

				$webhook->set_author_id( $user_id );
				$webhook->set_delivery_url( $hook_url );

				$deliver_callback = function( $webhook, $payload ) use ( $event ) {
					as_enqueue_async_action(
						'masteriyo/job/webhook',
						array(
							'event_name' => $event,
							'webhook'    => $webhook,
							'payload'    => $payload,
						),
						'masteriyo-webhooks'
					);
				};
				call_user_func( array( $listener, 'setup' ), $deliver_callback, $webhook );
			}
		}
	}
}
