<?php
namespace Uncanny_Automator\Integrations\Facebook_Lead_Ads;

use Uncanny_Automator\Integrations\Facebook_Lead_Ads\Facebook_Lead_Ads_App_Helpers;

/**
 * Class Lead_Created
 *
 * Represents a trigger for when a new lead is created in Facebook Lead Ads.
 * Extends App_Trigger for clean access to helpers, api, and webhooks dependencies.
 *
 * @package Uncanny_Automator\Integrations\Facebook_Lead_Ads\Triggers
 *
 * @property Facebook_Lead_Ads_App_Helpers $helpers
 * @property Facebook_Lead_Ads_Api_Caller $api
 * @property Facebook_Lead_Ads_Webhooks $webhooks
 */
class Lead_Created extends \Uncanny_Automator\Recipe\App_Trigger {

	/**
	 * Sets up the trigger properties.
	 *
	 * Defines integration, trigger code, trigger metadata, and type. Also configures
	 * sentences for describing the trigger.
	 *
	 * @link https://developer.automatorplugin.com/adding-a-custom-trigger-to-uncanny-automator/
	 *
	 * @return void
	 */
	protected function setup_trigger() {

		$this->set_integration( 'FACEBOOK_LEAD_ADS' );
		$this->set_trigger_code( 'FB_LEAD_ADS_CODE' );
		$this->set_trigger_meta( $this->helpers->get_const( 'TRIGGER_META' ) );
		$this->set_trigger_type( 'anonymous' );
		$this->set_uses_api( true );

		$this->set_sentence(
			sprintf(
				// translators: Trigger sentence
				esc_attr_x( 'A new lead from {{Page:%1$s}} is created', 'Facebook Lead Ads', 'uncanny-automator' ),
				$this->get_trigger_meta() // Returns string 'REDIRECT_TYPE'.
			)
		);

		$this->set_readable_sentence(
			esc_attr_x( '{{A new lead}} is created', 'Facebook Lead Ads', 'uncanny-automator' )
		);

		$this->add_action( Facebook_Lead_Ads_Webhooks::TRIGGER_ACTION_NAME, 10, 1 );
	}

	/**
	 * Check if trigger requirements are met.
	 *
	 * @return bool
	 */
	public function requirements_met() {
		return $this->helpers->has_connection();
	}

	/**
	 * Returns options for configuring the trigger.
	 *
	 * @return array[] An array of configuration options.
	 */
	public function options() {
		return array(
			array(
				'option_code'     => $this->get_trigger_meta(),
				'input_type'      => 'select',
				'label'           => esc_html_x( 'Page', 'Facebook Lead Ads', 'uncanny-automator' ),
				'required'        => true,
				'options'         => $this->helpers->get_pages_options(),
				'relevant_tokens' => array(),
			),
			array(
				'option_code'     => 'FORMS',
				'input_type'      => 'select',
				'label'           => esc_html_x( 'Form', 'Facebook Lead Ads', 'uncanny-automator' ),
				'description'     => esc_html_x( 'Updating a form in Facebook generates a new form ID, requiring you to reselect it from the dropdown.', 'Facebook Lead Ads', 'uncanny-automator' ),
				'required'        => true,
				'ajax'            => array(
					'endpoint'      => 'automator_facebook_lead_ads_forms_handler',
					'event'         => 'parent_fields_change',
					'listen_fields' => array( $this->get_trigger_meta() ),
				),
				'relevant_tokens' => array(),
			),
		);
	}

	/**
	 * Defines the tokens for this trigger.
	 *
	 * @param  array $tokens
	 * @param  array $trigger - options selected in the current recipe/trigger
	 *
	 * @return array
	 */
	public function define_tokens( $trigger, $tokens ) {

		$tokens[] = array(
			'tokenId'   => 'RAW_PAYLOAD',
			'tokenName' => esc_html_x( 'Raw payload (JSON)', 'Facebook Lead Ads', 'uncanny-automator' ),
		);

		$tokens[] = array(
			'tokenId'   => 'CREATED_TIME',
			'tokenName' => esc_html_x( 'Created time (timestamp)', 'Facebook Lead Ads', 'uncanny-automator' ),
		);

		$tokens[] = array(
			'tokenId'   => 'FORM_ID',
			'tokenName' => esc_html_x( 'Form ID', 'Facebook Lead Ads', 'uncanny-automator' ),
		);

		$tokens[] = array(
			'tokenId'   => 'LEADGEN_ID',
			'tokenName' => esc_html_x( 'Lead Gen ID', 'Facebook Lead Ads', 'uncanny-automator' ),
		);

		$tokens[] = array(
			'tokenId'   => 'PAGE_ID',
			'tokenName' => esc_html_x( 'Page ID', 'Facebook Lead Ads', 'uncanny-automator' ),
		);

		$form_fields = (array) maybe_unserialize( $trigger['meta'][ $this->helpers->get_const( 'FORM_FIELDS_META_KEY' ) ] ?? '' );

		foreach ( $form_fields as $fields ) {
			$tokens[] = array(
				'tokenId'   => $fields['key'] ?? '',
				'tokenName' => $fields['label'] ?? '',
			);
		}

		return $tokens;
	}

	/**
	 * Populate the tokens with actual values when a trigger runs.
	 *
	 * @param mixed[] $trigger The Trigger args.
	 * @param mixed[] $hook_args The accepted action hook arguments.
	 *
	 * @return mixed[]
	 */
	public function hydrate_tokens( $trigger, $hook_args ) {

		$payload = $hook_args[0]['data']['data'] ?? array();

		$json       = wp_json_encode( (array) $payload, true );
		$leadgen_id = $payload['leadgen_id'] ?? '';

		$token_values = array(
			'RAW_PAYLOAD'  => $json,
			'CREATED_TIME' => $payload['created_time'] ?? '',
			'PAGE_ID'      => $payload['page_id'] ?? '',
			'LEADGEN_ID'   => $leadgen_id,
			'FORM_ID'      => $payload['form_id'] ?? '',
		);

		$page_id = absint( $trigger['meta'][ $this->trigger_meta ] ?? 0 );

		// Use injected dependencies instead of direct class instantiation.
		$the_lead = $this->api->get_lead( $page_id, $leadgen_id );

		if ( is_wp_error( $the_lead ) ) {
			return $token_values;
		}

		$lead_field_values = $this->helpers->map_lead_data( (array) $the_lead );

		if ( ! empty( $lead_field_values ) ) {
			return array_merge( $token_values, $lead_field_values );
		}

		return $token_values;
	}

	/**
	 * Validates the trigger.
	 *
	 * Determines whether the trigger should fire based on supplied arguments.
	 *
	 * @param array{'ID': int, 'post_status': string, 'meta': mixed[]} $trigger   The arguments supplied by the trigger.
	 * @param mixed[]                                                $hook_args The action hook arguments.
	 *
	 * @return bool True if the trigger is valid, false otherwise.
	 */
	public function validate( $trigger, $hook_args ) {

		$entry = $hook_args[0]['data']['data'] ?? array();

		if ( empty( $entry ) ) {
			return false;
		}

		$selected_form_id = absint( $trigger['meta']['FORMS'] ?? 0 );
		$selected_page_id = absint( $trigger['meta'][ $this->get_trigger_meta() ] ?? 0 );

		if ( empty( $selected_form_id ) || empty( $selected_page_id ) ) {
			return false;
		}

		$entry_form_id = absint( $entry['form_id'] ?? 0 );
		$entry_page_id = absint( $entry['page_id'] ?? 0 );

		return $entry_form_id === $selected_form_id
			&& $entry_page_id === $selected_page_id;
	}
}
