<?php
/**
 * Plugin Action Links Class
 *
 * @package SAAI\Classes
 */

namespace SAAI\Classes;

use SAAI\Helpers\Connect;
use SAAI\Traits\Singleton_Trait;
use SAAI\Actions\Activation;
use SAAI\Helpers\Product;
use SAAI\AI_Agents\Product_Tags_Generator_AI;
use SAAI\REST\Product_Summaries_AI;
/**
 * Plugin Action Links Class
 *
 * This class adds action links to the plugin listing page.
 *
 * @since 1.0.2
 */
class Usage {

    use Singleton_Trait;

    const USAGE_CRON_ACTION  = 'saai_usage_tracking_cron';
    const USAGE_CRON_CONFIG  = 'saai_usage_tracking_cron_config';
    const USAGE_LAST_CHECKIN = 'saai_usage_tracking_last_checkin';

    /**
     * Schedule the usage tracking cron.
     *
     * @since 1.0.5
     * @access public
     */
    public function schedule_send() {
        $cron_schedule = wp_next_scheduled( self::USAGE_CRON_ACTION );

        // Skip if the cron is already scheduled.
        if ( $cron_schedule ) {
            return;
        }

        $tracking = array();
        // phpcs:disable
        $tracking['day']      = rand( 0, 6 );
        $tracking['hour']     = rand( 0, 23 );
        $tracking['minute']   = rand( 0, 59 );
        $tracking['second']   = rand( 0, 59 );
        // phpcs:enable
        $tracking['offset']   = ( $tracking['day'] * DAY_IN_SECONDS ) +
            ( $tracking['hour'] * HOUR_IN_SECONDS ) +
            ( $tracking['minute'] * MINUTE_IN_SECONDS ) +
            $tracking['second'];
        $tracking['initsend'] = strtotime( 'next sunday' ) + $tracking['offset'];

        // Schedule the main usage tracking event.
        wp_schedule_event( $tracking['initsend'], 'weekly', self::USAGE_CRON_ACTION );
        update_option( self::USAGE_CRON_CONFIG, $tracking );
    }

    /**
     * Send the checkin.
     *
     * @since 1.0.5
     * @access public
     *
     * @param bool $override            Flag to override if tracking is allowed or not.
     * @param bool $ignore_last_checkin Flag to ignore that last checkin time check.
     * @return bool Whether the checkin was sent successfully.
     */
    public function send_checkin( $override = false, $ignore_last_checkin = false ) {
        // Don't track anything from our domains.
        $home_url = trailingslashit( home_url() );
        if ( strpos( $home_url, 'storeagent.ai' ) !== false ) {
            return false;
        }

        $last_send = get_option( self::USAGE_LAST_CHECKIN );
        if ( is_numeric( $last_send ) && $last_send > strtotime( '-1 week' ) && ! ( $ignore_last_checkin || defined( 'SAAI_TESTING_SITE' ) ) ) {
            return false;
        }

        $response = wp_remote_post(
            'https://usg.rymeraplugins.com/v1/saai-checkin/',
            array(
                'method'      => 'POST',
                'timeout'     => 5,
                'redirection' => 5,
                'httpversion' => '1.1',
                'blocking'    => false,
                'body'        => $this->get_data(),
                'user-agent'  => 'SAAI/' . SAAI_VERSION . '; ' . get_bloginfo( 'url' ),
            )
        );

        // If we have completed successfully, recheck in 1 week.
        update_option( self::USAGE_LAST_CHECKIN, time() );
        return true;
    }

    /**
     * Get the data to send.
     *
     * @since 1.0.5
     * @access private
     * @return array The data to send.
     */
    private function get_data() {
        $data = array();

        $data['saai_version'] = SAAI_VERSION;
        $data['consumer_key'] = Connect::get_consumer_key();

        // Settings data.
        $this->append_settings_data( $data );

        // Environment data.
        $this->append_environment_data( $data );

        return $data;
    }

    /**
     * Append the settings data.
     *
     * @since 1.0.5
     * @access private
     * @param array $data The data to send.
     */
    private function append_settings_data( &$data ) {
        $data['settings'] = array();
        $ai_objects       = include SAAI_PLUGIN_DIR_PATH . 'bootstrap/ai-objects.php';

        foreach ( $ai_objects as $ai_object ) {
            $ai_settings = $ai_object->get_settings();

            foreach ( $ai_settings as $setting_key => $setting_value ) {
                $key                      = $ai_object->get_ai_id() . '_' . $setting_key;
                $data['settings'][ $key ] = $setting_value;
            }
        }
    }

    /**
     * Append server environment data.
     *
     * @since 1.0.5
     * @access private
     *
     * @param array $data Usage data.
     */
    private function append_environment_data( &$data ) {
        // Get current theme info.
        $theme_data = wp_get_theme();

        // Get multisite data.
        $count_blogs = 1;
        if ( is_multisite() ) {
            if ( function_exists( 'get_blog_count' ) ) {
                $count_blogs = get_blog_count();
            } else {
                $count_blogs = 'Not Set';
            }
        }

        $data['url']               = home_url();
        $data['php_version']       = phpversion();
        $data['wp_version']        = get_bloginfo( 'version' );
        $data['wc_version']        = \WC()->version;
        $data['server']            = isset( $_SERVER['SERVER_SOFTWARE'] ) ? $_SERVER['SERVER_SOFTWARE'] : ''; // phpcs:ignore
        $data['multisite']         = is_multisite();
        $data['sites']             = $count_blogs;
        $data['usercount']         = function_exists( 'count_users' ) ? count_users() : 'Not Set';
        $data['themename']         = $theme_data->Name; // phpcs:ignore
        $data['themeversion']      = $theme_data->version; // phpcs:ignore
        $data['admin_email']       = get_bloginfo( 'admin_email' );
        $data['usagetracking']     = get_option( self::USAGE_CRON_CONFIG, false );
        $data['timezoneoffset']    = wp_timezone_string();
        $data['locale']            = get_locale();
        $data['active_plugins']    = $this->get_active_plugins_data();
        $data['is_hpos_enabled']   = 'yes' === get_option( 'woocommerce_feature_custom_order_tables_enabled' );
        $data['is_cart_block']     = has_block( 'woocommerce/cart', wc_get_page_id( 'cart' ) );
        $data['is_checkout_block'] = has_block( 'woocommerce/checkout', wc_get_page_id( 'checkout' ) );

        // Product specific env data.
        $data['total_products']               = wp_count_posts( 'product' )->publish;
        $data['total_products_with_reviews']  = Product::get_total_products_with_meta_key_count( '_wc_average_rating' );
        $data['total_products_since_install'] = $this->get_total_products_since_install();
        $data['total_reviews']                = $this->get_total_reviews();

        // AI Data.
        $data['total_product_questions']     = Product_Question::get_questions_count();
        $data['total_review_summaries']      = Product::get_total_products_with_meta_key_count( Review_Summary::SUMMARY_META_KEY );
        $data['total_product_descriptions']  = Product::get_total_products_with_meta_key_count( Product_Description::META_KEY );
        $data['total_product_tags']          = Product::get_total_products_with_meta_key_count( Product_Tags_Generator_AI::GENERATED_TAGS_META_KEY );
        $data['total_category_descriptions'] = Product::get_total_categories_with_meta_key_count( Category_Description::META_KEY );
        $data['total_product_summaries']     = Product::get_total_products_with_meta_key_count( Product_Summaries_AI::PRODUCT_SUMMARY_META_KEY );
    }

    /**
     * Get site's list of active plugins.
     *
     * @since 1.0.5
     * @access private
     *
     * @return array List of active plugins.
     */
    private function get_active_plugins_data() {
        $active_plugins         = get_option( 'active_plugins', array() );
        $network_active_plugins = array_keys( get_site_option( 'active_sitewide_plugins', array() ) );

        return array_unique( array_merge( $active_plugins, $network_active_plugins ) );
    }

    /**
     * Get the total number of product reviews in the site.
     *
     * @since 1.0.5
     * @access private
     * @return int The total number of product reviews.
     */
    private function get_total_reviews() {
        $args = array(
            'post_type' => 'product',
            'status'    => 'approve',
            'type'      => 'review',
            'count'     => true,
        );

        return get_comments( $args );
    }

    /**
     * Get the total number of products created since plugin installation.
     *
     * @since 1.0.5
     * @access private
     * @return int The total number of products created since plugin installation.
     */
    private function get_total_products_since_install() {
        $install_date = get_option( Activation::PLUGIN_INSTALLED_TIMESTAMP );

        // If install date is not set, return 0.
        if ( ! $install_date ) {
            return 0;
        }

        $args = array(
            'post_type'      => 'product',
            'post_status'    => 'publish',
            'posts_per_page' => -1,
            'date_query'     => array(
                array(
                    'after'     => gmdate( 'c', $install_date ),
                    'inclusive' => true,
                ),
            ),
            'fields'         => 'ids',
        );

        $query = new \WP_Query( $args );
        return $query->found_posts;
    }

    /**
     * Add the cron schedule
     *
     * @since 1.0.5
     * @access public
     * @param array $schedules The schedules array from the filter.
     */
    public function add_schedules( $schedules = array() ) {
        // Adds once weekly to the existing schedules.
        $schedules['weekly'] = array(
            'interval' => 604800,
            'display'  => __( 'Once Weekly', 'storeagent-ai-for-woocommerce' ),
        );
        return $schedules;
    }

    /**
     * Add hooks and filters.
     *
     * @since 1.0.5
     * @access public
     */
    public function run() {
        // Don't enable tracking when the site is not yet connected to our server.
        if ( ! Connect::is_connected() ) {
            return;
        }

        add_filter( 'cron_schedules', array( $this, 'add_schedules' ) );
        add_action( 'init', array( $this, 'schedule_send' ) );
        add_action( self::USAGE_CRON_ACTION, array( $this, 'send_checkin' ) );
    }
}
