<?php

/**
 * Class WpmsGsc
 */
class WpmsGsc
{
    /**
     * Google search console service
     *
     * @var WpmsGscService
     */
    private $service;
    /**
     * WpmsGscCategoryFilters class
     *
     * @var object
     */
    protected $category_filter;
    /**
     * WpmsGscIssues class
     *
     * @var object
     */
    protected $issue_fetch;
    /**
     * Platform
     *
     * @var array|string
     */
    private $platform;
    /**
     * Category
     *
     * @var string
     */
    private $category;

    /**
     * WpmsGsc constructor.
     */
    public function __construct()
    {
        add_action('init', array($this, 'init'));
    }

    /**
     * Init
     *
     * @return void
     */
    public function init()
    {
        $page = filter_input(INPUT_GET, 'page');

        if ($page === 'metaseo_console' || $page === 'metaseo_settings') {
            $tab     = filter_input(INPUT_GET, 'tab');
            $profile = $this->getProfile();
            if ($tab !== 'settings' && $profile === '' && $page !== 'metaseo_settings') {
                $url = add_query_arg('tab', 'settings');
                wp_redirect($url);
                exit;
            }

            $this->setDepen();
            $this->requestHandler();
        }

        add_action('admin_init', array($this, 'registerSettings'));
    }

    /**
     * Register a setting and its sanitization callback
     *
     * @return void
     */
    public function registerSettings()
    {
        register_setting('wpms_gsc_options', WPMS_GSC);
    }

    /**
     * Display page gsc
     *
     * @return void
     */
    public function display()
    {
        wp_enqueue_script('wpms_script_gsc');
        wp_enqueue_style('wpmsaddon_gsc_style');
        $conn = get_option('wpms_gsc_connect');
        if (!empty($conn['googleClientId']) && !empty($conn['googleClientSecret'])) {
            $googleClientId     = $conn['googleClientId'];
            $googleClientSecret = $conn['googleClientSecret'];
        } else {
            $googleClientId     = '';
            $googleClientSecret = '';
        }

        $tabs        = $this->tabsHtml();
        $current_tab = $tabs['current_tab'];
        $html_tabs   = $tabs['html_tabs'];

        $screen = get_current_screen();
        if ($screen->base === 'wp-meta-seo_page_metaseo_console') {
            require_once WPMETASEO_ADDON_PLUGIN_DIR . 'inc/page/google_search_console/wpms-display.php';
        }

        if ($screen->base === 'wp-meta-seo_page_metaseo_settings') {
            require_once WPMETASEO_ADDON_PLUGIN_DIR . 'inc/page/google_search_console/wpms-display-settings.php';
        }
    }

    /**
     * Display the table
     *
     * @return void
     */
    public function displayTable()
    {
        // list table
        $list_table = new WpmsGscTable($this->platform, $this->category, $this->issue_fetch->getIssues());
        $list_table->searchBox(esc_html__('Search', 'wpmsPro'), 'wpms-crawl-issues-search');
        add_filter('views_' . $list_table->getScreenId(), array($this->category_filter, 'convertArray'));
        // Prepare and display table.
        $list_table->prepare_items();
        $list_table->display();
    }

    /**
     * Handles the POST and GET requests
     *
     * @return void
     */
    private function requestHandler()
    {
        // Catch author code
        $this->catchAuthorPost();
        // Catch profile
        $this->catchProfile();

        if (filter_input(INPUT_GET, 'gsc_reset')) {
            // Clear google data
            $this->clearData($this->service);
            delete_option('wpms_gsc_connect');
            $url = remove_query_arg('gsc_reset');
            wp_redirect($url);
            exit;
        }

        // Reload issues.
        if (wp_verify_nonce(filter_input(INPUT_POST, 'reload-crawl-issues-nonce'), 'reload-crawl-issues')
            && filter_input(INPUT_POST, 'reload-crawl-issues')) {
            self::remove();
        }

        // Catch bulk action request
        if (wp_verify_nonce(filter_input(INPUT_POST, 'wpms_gsc_nonce'), 'wpms_gsc_nonce')) {
            $bulk_action = $this->gscBulkAction();
            if ($bulk_action) {
                $i_posted = $this->issuePost();
                $this->runBulkAction($bulk_action, $i_posted);
                $url = filter_input(INPUT_POST, '_wp_http_referer');
                wp_redirect($url);
                exit;
            }
        }

        // List table search post.
        $s = filter_input(INPUT_POST, 's');
        if ($s !== null) {
            $url = ($s !== '') ? add_query_arg('s', $s) : remove_query_arg('s');
            wp_redirect($url);
            exit;
        }
    }

    /**
     * Determine which bulk action is selected and return that value
     *
     * @return boolean|mixed
     */
    private function gscBulkAction()
    {
        $action = filter_input(INPUT_POST, 'action');
        if (($action) && $action !== '-1') {
            return $action;
        }

        $action = filter_input(INPUT_POST, 'action2');
        if (($action) && $action !== '-1') {
            return $action;
        }

        return false;
    }

    /**
     * Get the posted issues and return them
     *
     * @return array|mixed
     */
    private function issuePost()
    {
        $issues = filter_input(INPUT_POST, 'wpms_crawl_issues', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY);
        if ($issues) {
            return $issues;
        }

        return array();
    }

    /**
     * Runs the bulk action
     *
     * @param string $action Action type.
     * @param array  $issues Set of issues to apply to.
     *
     * @return void
     */
    private function runBulkAction($action, $issues)
    {
        switch ($action) {
            case 'mark_as_fixed':
                array_map(array($this, 'actionMark'), $issues);
                break;
        }
    }

    /**
     * Marks the issue as fixed
     *
     * @param string $issue Issue URL.
     *
     * @return string
     */
    private function actionMark($issue)
    {
        new WpmsGscMarker($issue);
        return $issue;
    }

    /**
     * Setting dependencies
     *
     * @return void
     */
    private function setDepen()
    {
        // Set service
        $this->service  = new WpmsGscService($this->getProfile());
        $this->platform = WpmsGscMapper::getCurrentPlat('tab');
        // Load issue count.
        $issue_count = new WpmsGscCount($this->service);
        $issue_count->fetchCounts();
        // Load category filter
        $this->category_filter = new WpmsGscCategoryFilters($issue_count->countsPlat($this->platform));
        // Setcurrent category.
        $this->category = $this->category_filter->getCategory();
        // List issue.
        $issue_count->listIssues($this->platform, $this->category);
        // Fetch issue
        $this->issue_fetch = new WpmsGscIssues($this->platform, $this->category, $issue_count->getIssues());
    }

    /**
     * Catch the authentication post
     *
     * @return void
     */
    private function catchAuthorPost()
    {
        $gsc_api = filter_input(INPUT_POST, 'gscapi', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY);
        // Catch authorization code
        if (!empty($gsc_api['save'])) {
            if (isset($gsc_api['googleClientId']) && isset($gsc_api['googleClientSecret'])) {
                $conn = array(
                    'googleClientId'     => $gsc_api['googleClientId'],
                    'googleClientSecret' => $gsc_api['googleClientSecret']
                );
                update_option('wpms_gsc_connect', $conn);
                $this->service = new WpmsGscService($this->getProfile());
                $authUrl = $this->service->getClient()->createAuthUrl();
                wp_redirect($authUrl);
                exit();
            }
        }

        $gsc_values = filter_input(INPUT_POST, 'gsc', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY);
        if (!empty($gsc_values['authorization_code']) && wp_verify_nonce($gsc_values['gsc_nonce'], 'wpms-gsc_nonce')) {
            $this->validateAuthorization(trim($gsc_values['authorization_code']), $this->service->getClient());
            // Do redirect
            $url = admin_url('admin.php') . '?page=' . esc_attr(filter_input(INPUT_GET, 'page')) . '&tab=settings';
            wp_redirect($url);
            exit;
        }
    }

    /**
     * Authentication
     *
     * @param string $authorization_code Authorization code
     *
     * @return void
     */
    public function authenticate($authorization_code)
    {

        $this->service = new WpmsGscService($this->getProfile());
        $this->validateAuthorization($authorization_code, $this->service->getClient());
    }

    /**
     * Catch the Profile
     *
     * @return void
     */
    private function catchProfile()
    {
        $gsc_pf = filter_input(INPUT_POST, 'wpms-gsc-pf', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY);

        // Catch profile
        if (!empty($gsc_pf['submit']) && wp_verify_nonce($gsc_pf['gsc_pf_nonce'], 'gsc_pf_nonce')) {
            if (isset($gsc_pf['profile']) && !empty($gsc_pf['profile'])) {
                update_option(WPMS_GSC, array('profile' => $gsc_pf['profile']));

                $this->service = new WpmsGscService($this->getProfile());

                // Do redirect
                $url = admin_url('admin.php') . '?page=' . esc_attr(filter_input(INPUT_GET, 'page')) . '&tab=settings#search_console';
                wp_redirect($url);
                exit;
            }
        }


        // Reauthenticate
        if (!empty($gsc_pf['reauthenticate']) && wp_verify_nonce($gsc_pf['gsc_pf_nonce'], 'gsc_pf_nonce')) {
            // Clear google data
            $this->clearData($this->service);
            delete_option('wpms_gsc_connect');

            // Do redirect
            $url = admin_url('admin.php') . '?page=' . esc_attr(filter_input(INPUT_GET, 'page')) . '&tab=settings#search_console';
            wp_redirect($url);
            exit;
        }
    }

    /**
     * Gererate tabs
     *
     * @return array
     */
    public function tabsHtml()
    {
        $tabs = array('settings' => esc_html__('Settings', 'wpmsPro'));

        $plat = array(
            'web'             => esc_html__('Desktop', 'wpmsPro'),
            'smartphone_only' => esc_html__('Smartphone', 'wpmsPro'),
            'mobile'          => esc_html__('Feature phone', 'wpmsPro'),
        );

        if ($this->getProfile() !== '') {
            $tabs = array_merge($plat, $tabs);
        }

        $current_tab  = key($tabs);
        $current_plat = filter_input(INPUT_GET, 'tab');
        if ($current_plat) {
            $current_tab = $current_plat;
        }

        $html_tabs = '';

        foreach ($tabs as $k => $v) {
            $html_tabs .= $this->tabHtml($k, $v, $current_tab);
        }

        return array('current_tab' => $current_tab, 'html_tabs' => $html_tabs);
    }

    /**
     * Gererate tabs
     *
     * @param string $platform_target Platform target
     * @param string $platform_value  Platform value
     * @param string $current_tab     Current tab
     *
     * @return string
     */
    public function tabHtml($platform_target, $platform_value, $current_tab)
    {
        $admin_link = admin_url('admin.php?page=metaseo_console&tab=');
        $li         = '<li class="tab wpmstab col">';
        $li         .= '<a href="' . esc_url($admin_link . $platform_target) . '">' . esc_html($platform_value) . '</a>';
        if ($current_tab === $platform_target) {
            $li .= '<div class="indicator" style="bottom: 0; left: 0;width:100%"></div>';
        }

        $li .= '</li>';
        return $li;
    }

    /**
     * Clear all data from the database
     *
     * @param WpmsGscService $service Service class instance.
     *
     * @return void
     */
    public static function clearData(WpmsGscService $service)
    {
        self::remove();
        delete_option(WPMS_GSC);
        $service->clearData();
    }

    /**
     * Validate authorization
     *
     * @param string                 $author_code Code to validate.
     * @param Wpms_Api_Google_Client $client      Client object instance.
     *
     * @return boolean
     */
    public static function validateAuthorization($author_code, Wpms_Api_Google_Client $client)
    {
        return ($author_code !== '' && $client->authenticate_client($author_code));
    }

    /**
     * Get the GSC profile
     *
     * @return string
     */
    public static function getProfile()
    {
        $option  = get_option(WPMS_GSC, array('profile' => ''));
        $profile = '';
        if (!empty($option['profile'])) {
            $profile = $option['profile'];
        }

        return trim($profile, '/');
    }

    /**
     * Remove the issues
     *
     * @return void
     */
    private static function removeIssues()
    {
        global $wpdb;
        $wpdb->query('DELETE FROM ' . $wpdb->options . ' WHERE option_name LIKE "wpms-gsc-issues-%"');
    }

    /**
     * Removes the issue counts and all the issues
     *
     * @return void
     */
    private static function remove()
    {
        self::removeIssueCounts();
        self::removeIssues();
    }

    /**
     * Remove the issue counts
     *
     * @return void
     */
    private static function removeIssueCounts()
    {
        delete_option(WPMS_GSC_COUNTS);
        delete_option(WPMS_GSC_LAST_FETCH);
    }
}
