<?php

use Automattic\WooCommerce\Blocks\Integrations\IntegrationInterface;
use Automattic\WooCommerce\Blocks\Package;
use Automattic\WooCommerce\Blocks\Domain\Services\ExtendRestApi;
use Automattic\WooCommerce\Blocks\StoreApi\Schemas\CheckoutSchema;
use Automattic\WooCommerce\StoreApi\StoreApi;
use Automattic\WooCommerce\StoreApi\Schemas\ExtendSchema;
defined( 'ABSPATH' ) || exit;

/**
 * Class Mailchimp_Woocommerce_Newsletter_Blocks_Integration
 *
 * Class for integrating marketing optin block with WooCommerce Checkout
 *
 */
class Mailchimp_Woocommerce_Newsletter_Blocks_Integration implements IntegrationInterface {

	/**
	 * The name of the integration.
	 *
	 * @return string
	 */
	public function get_name()
    {
		return 'mailchimp-newsletter';
	}

	/**
	 * @throws Exception
	 */
	public function initialize()
    {
		$this->register_frontend_scripts();
        $this->register_editor_scripts();
		$this->register_editor_blocks();
		$this->extend_store_api();
		add_filter( '__experimental_woocommerce_blocks_add_data_attributes_to_block', [ $this, 'add_attributes_to_frontend_blocks' ], 10, 1 );
        add_action('woocommerce_before_order_object_save', [$this, 'capture_from_store_api'], 1);
        add_action('woocommerce_blocks_checkout_update_order_from_request', [$this, 'order_processed'], 10, 2);
        //add_action('woocommerce_blocks_checkout_order_processed', [$this, 'order_processed'], 10, 2);
	}

	/**
	 * @return bool
	 */
	public function register_frontend_scripts()
    {
		$script_path       = '/build/newsletter-block-frontend.js';
		$script_url        = plugins_url( $script_path, __FILE__ );
		$script_asset_path = dirname( __FILE__ ) . '/build/newsletter-block-frontend.asset.php';
		$script_asset      = file_exists( $script_asset_path )
			? require $script_asset_path
			: array(
				'dependencies' => array(),
				'version'      => $this->get_file_version( $script_asset_path ),
			);

		$result = wp_register_script(
			'mailchimp-newsletter-frontend',
			$script_url,
			$script_asset['dependencies'],
			$script_asset['version'],
			true
		);

		if (!$result) {
		    return false;
        }

		wp_set_script_translations(
			'mailchimp-newsletter-frontend', // script handle
			'mailchimp-woocommerce', // text domain
			dirname(dirname( __FILE__ )) . '/languages'
		);
		return true;
	}

    public function register_editor_scripts()
    {
        $script_path       = '/build/newsletter-block.js';
        $script_url        = plugins_url( $script_path, __FILE__ );
        $script_asset_path = dirname( __FILE__ ) . '/build/newsletter-block.asset.php';
        $script_asset      = file_exists( $script_asset_path )
            ? require $script_asset_path
            : array(
                'dependencies' => array(),
                'version'      => $this->get_file_version( $script_asset_path ),
            );

        wp_register_script(
            'mailchimp-newsletter-editor',
            $script_url,
            $script_asset['dependencies'],
            $script_asset['version'],
            true
        );

        wp_set_script_translations(
            'mailchimp-newsletter-editor', // script handle
            'mailchimp-woocommerce', // text domain
            dirname(dirname( __FILE__ )) . '/languages'
        );
    }

	/**
	 * Returns an array of script handles to enqueue in the frontend context.
	 *
	 * @return string[]
	 */
	public function get_script_handles()
    {
		return array(
		    'mailchimp-newsletter-frontend'
        );
	}

	/**
	 * Returns an array of script handles to enqueue in the editor context.
	 *
	 * @return string[]
	 */
	public function get_editor_script_handles()
    {
		return array(
            'mailchimp-newsletter-editor'
        );
	}

	/**
	 * An array of key, value pairs of data made available to the block on the client side.
	 *
	 * @return array
	 */
	public function get_script_data()
    {
        $gdpr = $this->getGdprFields();
        $data = array(
            'optinDefaultText' => __( 'I want to receive updates about products and promotions.', 'mailchimp-newsletter' ),
        );

        if (!empty($gdpr)) {
            $data['gdprHeadline'] = __( 'Please select all the ways you would like to hear from us', 'mailchimp-newsletter' );
            $data['gdprFields'] = $gdpr;
        }

		return $data;
	}

	/**
	 * Register blocks.
	 */
	public function register_editor_blocks()
    {
        register_block_type( dirname( __FILE__ ) . '/assets/js/checkout-newsletter-subscription-block', array(
            'editor_script' => 'mailchimp-newsletter-editor',
        ));
	}

	/**
	 * This allows dynamic (JS) blocks to access attributes in the frontend.
	 *
	 * @param $allowed_blocks
	 *
	 * @return mixed
	 */
	public function add_attributes_to_frontend_blocks( $allowed_blocks )
    {
    	if (!is_array($allowed_blocks)) {
    		$allowed_blocks = (array) $allowed_blocks;
	    }
		$allowed_blocks[] = 'woocommerce/mailchimp-newsletter-subscription';
		return $allowed_blocks;
	}

	/**
	 * @throws Exception
	 */
	public function extend_store_api()
    {
        /** @var ExtendRestApi $extend */
        /** @var ExtendSchema $extend */
		$extend = class_exists('Automattic\WooCommerce\StoreApi\Schemas\ExtendSchema') ? StoreApi::container()->get(ExtendSchema::class) : Package::container()->get(ExtendRestApi::class);

		$extend->register_endpoint_data(
			array(
				'endpoint'        => CheckoutSchema::IDENTIFIER,
				'namespace'       => $this->get_name(),
				'schema_callback' => function() {
					return array(
						'optin' => array(
							'description' => __( 'Subscribe to marketing opt-in.', 'mailchimp-newsletter' ),
							'type'        => 'boolean',
							'context'     => array(),
							'arg_options' => array(
								'validate_callback' => function( $value ) {
									if ( ! is_bool( $value ) ) {
										return new WP_Error( 'api-error', 'value of type ' . gettype( $value ) . ' was posted to the newsletter optin callback' );
									}
									return true;
								},
							),
						),
                        'gdprFields' => array(
                            'description' => __( 'GDPR marketing opt-in.', 'mailchimp-newsletter' ),
                            'type'        => 'object',
                            'context'     => array(),
                            'arg_options' => array(
                                'validate_callback' => function( $value ) {
                                    return true;
                                },
                            ),
                        ),
					);
				},
			)
		);
	}

	/**
	 * Store guest info when they submit email from Store API.
	 *
	 * The guest email, first name and last name are captured.
	 *
	 * @see \Automattic\WooCommerce\Blocks\StoreApi\Routes\CartUpdateCustomer
	 *
	 * @param WC_Order|WC_Order_Refund $order
	 *
	 * @throws MailChimp_WooCommerce_Error
	 * @throws MailChimp_WooCommerce_RateLimitError
	 * @throws MailChimp_WooCommerce_ServerError
	 */
    public function capture_from_store_api($order)
    {
        if ($order->get_status() !== 'checkout-draft' ||
            !$order->is_created_via( 'store-api' ) ||
            !$order->get_billing_email()) {
            return;
        }

        if (!($api = $this->api())) {
            return;
        }

        // this should allow us to do the same thing as previous without the javascript hook
        $service = MailChimp_Service::instance();
        $service->set_user_from_block_checkout($order->get_billing_email());
        $service->handleCartUpdated();
    }

    /**
     * @param WC_Order $order
     * @param $request
     */
    public function order_processed($order, $request)
    {
        $meta_key = 'mailchimp_woocommerce_is_subscribed';
        $optin = $request['extensions']['mailchimp-newsletter']['optin'];
        $gdpr_fields = isset($request['extensions']['mailchimp-newsletter']['gdprFields']) ?
            (array) $request['extensions']['mailchimp-newsletter']['gdprFields'] : null;

        // update the order meta for the subscription status to support legacy functions
        update_post_meta($order->get_id(), $meta_key, $optin);
        // let's set the GDPR fields here just in case we need to pull them again.
        if (!empty($gdpr_fields)) {
            update_post_meta($order->get_id(), "mailchimp_woocommerce_gdpr_fields", $gdpr_fields);
        }

        // if the user id exists
        if (($user_id = $order->get_user_id())) {
            // update the user subscription meta
            update_user_meta($user_id, $meta_key, $optin);
            // submit this if there's a proper user ID and is a subscriber.
            if ((bool) $optin) {
                // probably need to add the GDPR fields and language in to this submission next.
                $language = null;
                mailchimp_handle_or_queue(
                    new MailChimp_WooCommerce_User_Submit(
                        $user_id,
                        true,
                        null,
                        $language,
                        $gdpr_fields
                    )
                );
            }
        }

        $tracking = MailChimp_Service::instance()->onNewOrder($order->get_id());
        // queue up the single order to be processed.
        $campaign_id = isset($tracking) && isset($tracking['campaign_id']) ? $tracking['campaign_id'] : null;
        $landing_site = isset($tracking) && isset($tracking['landing_site']) ? $tracking['landing_site'] : null;
        $language = substr( get_locale(), 0, 2 );

        // update the post meta with campaign tracking details for future sync
        if (!empty($campaign_id)) {
            update_post_meta($order->get_id(), 'mailchimp_woocommerce_campaign_id', $campaign_id);
        }
        if (!empty($landing_site)) {
            update_post_meta($order->get_id(), 'mailchimp_woocommerce_landing_site', $landing_site);
        }

        $handler = new MailChimp_WooCommerce_Single_Order($order->get_id(), null, $campaign_id, $landing_site, $language, $gdpr_fields);
        $handler->is_update = false;
        $handler->is_admin_save = is_admin();

        mailchimp_handle_or_queue($handler, 15);
    }

    /**
     * @return bool|MailChimp_WooCommerce_MailChimpApi
     */
    protected function api()
    {
        if (!mailchimp_is_configured()) {
            return false;
        }
        return mailchimp_get_api();
    }

    /**
     * @return array
     */
	protected function getGdprFields()
    {
        if (!mailchimp_is_configured()) {
            return array();
        }
        if (!($list_id = mailchimp_get_list_id())) {
            return array();
        }
        $fields = mailchimp_get_api()->getCachedGDPRFields($list_id);
        return is_array($fields) ? $fields : array();
    }

	/**
	 * Get the file modified time as a cache buster if we're in dev mode.
	 *
	 * @param string $file Local path to the file.
	 * @return string The cache buster value to use for the given file.
	 */
	protected function get_file_version( $file )
    {
		if ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG && file_exists( $file ) ) {
			return filemtime( $file );
		}
		return MAILCHIMP_WOOCOMMERCE_NEWSLETTER_VERSION;
	}
}
