<?php namespace Tussendoor\Reloadify\Controllers;

use Tussendoor\Reloadify\Concerns\HasActions;
use Tussendoor\Reloadify\Helpers\Request;
use Tussendoor\Reloadify\Plugin;

class PublicController extends Controller
{

    use HasActions;

    /**
     * The recovery key to use for the session hash
     *
     * @var string
     */
    protected $recoveryKey;

    /**
     * The key that will be passed by the admin while recovering a cart
     *
     * @since 1.4.0
     * @var string
     */
    protected $recoveryAdminKey;

    public function register()
    {
        $this->setProperties();
        $this->addActions();
    }

    public function setProperties()
    {
        $this->recoveryKey      = Plugin::config('plugin.recovery_parameter');
        $this->recoveryAdminKey = Plugin::config('plugin.recovery_admin_parameter');
    }

    public function addActions()
    {
        add_action('wp_loaded', [$this, 'handleReloadifyHash']);
        add_action('wp_ajax_' . self::$forgetAdminRecoveryAction, [$this, 'forgetAdminRecovery']);
        add_action('wp_ajax_nopriv_' . self::$forgetAdminRecoveryAction, [$this, 'forgetAdminRecovery']);
    }

    /**
     * Handle our custom sessions hash
     *
     * @since 1.4.0 The reloadify_hash is no longer the same as the cart hash. As this wasnt reliable enough.
     *              A unique string is sufficent.
     *
     * @return void
     */
    public function handleReloadifyHash()
    {
        if (!function_exists('WC') || is_admin() || WC()->is_rest_api_request()) return;

        if (empty(WC()->session)) {
            WC()->initialize_session();
        }

        if (!WC()->session->has_session()) {
            WC()->session->set_customer_session_cookie(true);
        }

        $wcSession  = WC()->session;
        $request    = Request::fromGlobal();

        // If our recovery key is set, set the custom session hash to the recovery key as fast as possible
        if ($request->has($this->recoveryKey)) {
            return $this->handleCartRecovery($request, $wcSession);
        }

        // If the session does not contain a unique customer id, remove possible existing custom hash
        if (empty(WC()->session->get_customer_unique_id())) {
            return $wcSession->__unset('reloadify_hash');
        }

        // First time saving the reloadify_hash to the session
        // We do not want to set the reloadify_hash during the admin recovery session
        if (!$wcSession->__isset('reloadify_hash') && !$this->isReloadifyAdminRecovery()) {
            $hash = md5(uniqid(rand(), true)) . time();
            return $wcSession->set('reloadify_hash', $hash);
        }
    }

    /**
     * Handle the cart recovery
     *
     * @since 1.4.0 Forget the current session when we are recovering a cart
     *
     * @param  Request $request
     * @param  \WC_Session $wcSession
     * @return void
     */
    private function handleCartRecovery(Request $request, \WC_Session $wcSession)
    {
        $recoveryHash = $request->getKey($this->recoveryKey);

        // When we are recovering we want to forget the current/previous session
        WC()->session->forget_session();

        if ($this->isReloadifyAdminRecovery()) {
            WC()->session->__unset('reloadify_hash');
            return $wcSession->set('reloadify_admin_recovery', $recoveryHash);
        }

        return $wcSession->set('reloadify_hash', $recoveryHash);
    }

    /**
     * Check if the current request is a Reloadify admin recovery request
     *
     * @return bool
     */
    public function isReloadifyAdminRecovery()
    {
        $request = Request::fromGlobal();
        return ($request->has($this->recoveryKey) && $request->has($this->recoveryAdminKey)) || $this->isReloadifyAdminRecoverySession();
    }

    /**
     * Check if the current session is a Reloadify admin recovery session
     *
     * @return bool
     */
    public function isReloadifyAdminRecoverySession()
    {
        if (!function_exists('WC') || empty(WC()->session) || !WC()->session->has_session()) return false;

        return !empty(WC()->session->get('reloadify_admin_recovery'));
    }

    /**
     * Forget the current admin recovery session keys and empty the cart
     *
     * @since 1.4.0
     *
     * @return void
     */
    public function forgetAdminRecovery()
    {
        if (!function_exists('WC') || empty(WC()->session) || !WC()->session->has_session()) return;

        WC()->session->__unset('reloadify_admin_recovery');
        WC()->session->__unset('reloadify_hash');

        if (!empty(WC()->cart)) {
            WC()->cart->empty_cart();
        }

        wp_send_json_success();
    }
}
