<?php

declare( strict_types=1 );

namespace DocketConnector\GravityForms;

use DocketConnector\Bootstrap;
use DocketConnector\PluginData;
use GFAddOn;
use GFAPI;
use GFCommon;
use GFForms;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Abort if this file is called directly.
}

if ( ! class_exists( Setup::class ) ) {
	/**
	 * The Gravity Forms setup.
	 */
	class Setup {

		/**
		 * The minimum version of Gravity Forms that we support.
		 *
		 * @todo Keep up with the most recent version of the @since tags from the GFPaymentAddOn class.
		 *
		 * @see  \DocketConnector\Bootstrap::$required_plugins
		 *
		 * @var string
		 */
		public static $gravity_forms_version_min = '2.4.18';

		/**
		 * Our custom Gravity Forms link.
		 *
		 * @var string
		 */
		public static $gravity_forms_affiliate_link = 'https://rocketgenius.pxf.io/aVVqM';

		/**
		 * Our custom Gravity Forms capability.
		 *
		 * @return string Unless filtered: 'gravityforms_docket_invoice_connector'.
		 */
		public static function get_gravity_forms_capability(): string {
			$cap = 'gravityforms_' . PluginData::plugin_text_domain_underscores();

			return apply_filters( PluginData::plugin_text_domain_underscores() . '_' . __FUNCTION__, $cap );
		}

		/**
		 * Determine if Gravity Forms plugin is active and of an acceptable version.
		 *
		 * @see \DocketConnector\Bootstrap::$required_plugins
		 *
		 * @return bool Whether Gravity Forms is active and is of an acceptable version.
		 */
		public function is_gravity_forms_ready(): bool {
			return ( new Bootstrap() )->is_plugin_active_and_sufficient_version( 'gravityforms', static::$gravity_forms_version_min );
		}

		/**
		 * Register the Gravity Forms Add-Ons from this plugin.
		 */
		public function load_addons(): void {
			if ( ! method_exists( 'GFForms', 'include_feed_addon_framework' ) ) {
				return;
			}

			GFForms::include_feed_addon_framework();

			// Once per Gravity Forms Add-On from this plugin.
			GFAddOn::register( Invoice::class );
		}

		/**
		 * Add the Docket meta box to the single entry admin page.
		 *
		 * @see \GFEntryDetail::add_meta_boxes()
		 *
		 * @param array $meta_boxes The properties for the meta boxes.
		 * @param array $entry      The entry currently being viewed/edited.
		 * @param array $form       The form object used to process the current entry.
		 *
		 * @return array
		 */
		public function single_entry_add_docket_meta_box(
			array $meta_boxes,
			array $entry,
			array $form
		): array {
			if ( ! GFCommon::current_user_can_any( 'gravityforms_edit_entry_notes' ) ) {
				return $meta_boxes;
			}

			$invoice = Invoice::get_instance();

			// Don't show the Docket meta box if there is not an active Invoice feed. @todo maybe still show if has past attempts.
			if ( ! $invoice->has_feed( $form['id'] ) ) {
				return $meta_boxes;
			}

			$meta_boxes['docket_connector'] = [
				'title'    => sprintf(
					'<span aria-hidden="true" style="padding-right: 5px;">%s</span> %s',
					$invoice->get_docket_icon_for_settings( '16px' ), // The size that doesn't cause panel height to increase.
					esc_html_x(
						'Docket Connector',
						'single entry meta box title',
						'docket-connector'
					)
				),
				'callback' => [ new MetaBox(), 'single_entry_add_docket_meta_box' ],
				'context'  => 'side',
			];

			return $meta_boxes;
		}

		/**
		 * Try sending Invoice to Docket after completed payment, since Entry may not have Payment Amount at the time
		 * the feed initially fires (e.g. Authorize.net authorizes successful payment at Entry creation but its payment
		 * amount does not get logged until Entry update).
		 *
		 * @link  https://docs.gravityforms.com/gform_post_payment_completed/
		 *
		 * @see   \GFPaymentAddOn::complete_payment()
		 * @see   \DocketConnector\GravityForms\AbstractFeedAddOn::process_feed()
		 *
		 * @since 1.1.2 No longer disallow sending to Docket if had a previous success.
		 *
		 * @param array $entry  The entry array.
		 * @param array $action The payment action array.
		 */
		public function try_invoice_upon_payment_completed(
			array $entry,
			array $action
		): void {
			// Bail if way wrong.
			if (
				empty( $entry['id'] )
				|| empty( $entry['form_id'] )
			) {
				return;
			}

			$form = GFAPI::get_form( $entry['form_id'] );

			if (
				empty( $form )
				|| ! is_array( $form )
			) {
				return;
			}

			$invoice = Invoice::get_instance();

			$invoice->maybe_process_feed( $entry, $form );
		}
	}
}