<?php
/**
 * AuctionForge Site Statistics - Initialization
 * Loads all stats classes, registers hooks, enqueues tracker script.
 */

if (!defined('ABSPATH')) exit;

class AF_Stats_Init {

    private static $initialized = false;

    public static function init() {
        if (self::$initialized) return;
        self::$initialized = true;

        $dir = plugin_dir_path(__FILE__);
        require_once $dir . 'class-stats-database.php';
        require_once $dir . 'class-stats-tracker.php';
        require_once $dir . 'class-stats-ajax.php';
        require_once $dir . 'class-visitor-email-map.php';
        require_once $dir . 'class-keyword-extractor.php';
        require_once $dir . 'class-user-interests.php';

        // Marketing-data sync handlers (Phase 2 of the cross-site data lake).
        $sync_dir = dirname($dir) . '/sync/';
        require_once $sync_dir . 'class-sync-base.php';
        require_once $sync_dir . 'class-profile-sync.php';
        require_once $sync_dir . 'class-interests-sync.php';
        require_once $sync_dir . 'class-activity-sync.php';
        require_once $sync_dir . 'class-lots-sync.php';
        require_once $sync_dir . 'class-bids-sync.php';

        // Retention purge cron.
        require_once dirname($dir) . '/maintenance/class-data-purge.php';
        AF_Data_Purge::register();

        // Register all sync crons (idempotent — wp_schedule_event guards).
        if (!empty(get_option('auctionforge_update_server_url'))
            && !empty(get_option('auctionforge_update_api_key'))) {
            (new AF_Profile_Sync())->register();
            (new AF_Interests_Sync())->register();
            (new AF_Activity_Sync())->register();
            (new AF_Lots_Sync())->register();
            (new AF_Bids_Sync())->register();
        }

        // Pre-extract keywords whenever a lot is created/updated.
        add_action('save_post_lot', array('AF_Keyword_Extractor', 'on_save_post'), 20, 3);

        // Refresh the user's profile row on wpdeploy whenever they log in or
        // edit their profile. Bypasses the watermark so empty/stale rows
        // pick up the latest first_name/last_name/phone/postcode immediately
        // — instead of waiting for the next hourly walk (which only re-pulls
        // newly-registered users).
        add_action('wp_login', function ($user_login, $user) {
            if ($user && class_exists('AF_Profile_Sync')) {
                AF_Profile_Sync::push_for_user_id($user->ID);
            }
        }, 10, 2);
        add_action('profile_update', function ($user_id) {
            if (class_exists('AF_Profile_Sync')) {
                AF_Profile_Sync::push_for_user_id((int) $user_id);
            }
        }, 10, 1);
        add_action('user_register', function ($user_id) {
            if (class_exists('AF_Profile_Sync')) {
                AF_Profile_Sync::push_for_user_id((int) $user_id);
            }
        }, 10, 1);

        // After AF_Stats_Ajax records the visitor→email pair, also tally
        // a lot view in user_interests if the URL belongs to a lot.
        add_action('af_stats_pageview_recorded', array(__CLASS__, 'maybe_record_lot_view'), 10, 3);

        // Wire the existing favourite/share AJAX into UserInterests.
        add_action('af_stats_lot_favorited', array(__CLASS__, 'record_lot_favorite'), 10, 2);

        // Register AJAX handlers
        AF_Stats_Ajax::init();

        // Enqueue frontend tracker on non-admin pages
        add_action('wp_enqueue_scripts', array(__CLASS__, 'enqueue_tracker'));

        // Track 404 errors server-side
        add_action('template_redirect', array(__CLASS__, 'track_404'));

        // Admin menu
        if (is_admin()) {
            add_action('admin_menu', array(__CLASS__, 'register_admin_menu'));
        }

        // Auto-create tables if they don't exist (handles updates, not just activation)
        add_action('plugins_loaded', array(__CLASS__, 'maybe_create_tables'), 20);

        // Data retention cron
        add_action('af_stats_daily_purge', array('AF_Stats_Database', 'purge_old_data'));
        if (!wp_next_scheduled('af_stats_daily_purge')) {
            wp_schedule_event(time(), 'daily', 'af_stats_daily_purge');
        }
    }

    /**
     * Enqueue the lightweight tracker JS on the frontend
     */
    public static function enqueue_tracker() {
        if (get_option('af_stats_enabled', 'on') !== 'on') return;

        // Check if should skip (excluded roles, IPs)
        if (AF_Stats_Tracker::should_skip()) return;

        // Check bot
        $ua = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '';
        if (AF_Stats_Tracker::is_bot($ua)) return;

        $plugin_url = plugin_dir_url(dirname(dirname(__FILE__)));
        $version = defined('AUCTIONFORGE_VERSION') ? AUCTIONFORGE_VERSION : '1.0';

        wp_enqueue_script(
            'af-stats-tracker',
            $plugin_url . 'assets/js/af-stats-tracker.js',
            array(),
            $version,
            true
        );

        wp_add_inline_script('af-stats-tracker', 'window.af_stats_config = ' . wp_json_encode(array(
            'ajax_url' => admin_url('admin-ajax.php'),
            'nonce' => wp_create_nonce('af_stats_nonce'),
        )) . ';', 'before');
    }

    /**
     * Track 404 errors server-side
     */
    public static function track_404() {
        if (!is_404()) return;
        if (get_option('af_stats_enabled', 'on') !== 'on') return;

        $ua = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '';
        if (AF_Stats_Tracker::is_bot($ua)) return;

        $url = (is_ssl() ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
        $referrer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '';
        $ip = AF_Stats_Tracker::get_client_ip();
        $ip = AF_Stats_Tracker::maybe_anonymize_ip($ip);

        // We don't have visitor_hash server-side, use IP hash
        $visitor_hash = md5($ip . $ua);

        AF_Stats_Tracker::record_404($url, $referrer, $visitor_hash, $ip);
    }

    /**
     * Register admin menu page
     */
    public static function register_admin_menu() {
        add_submenu_page(
            'edit.php?post_type=lot',
            __('Site Statistics', 'auctionforge'),
            __('Site Statistics', 'auctionforge'),
            'manage_options',
            'auctionforge-stats',
            array(__CLASS__, 'render_admin_page')
        );
    }

    /**
     * Render admin dashboard
     */
    public static function render_admin_page() {
        require_once plugin_dir_path(dirname(dirname(__FILE__))) . 'admin/view/stats/dashboard.php';
    }

    /**
     * Hook handler — fires after AF_Stats_Ajax records a pageview.
     * If the URL resolves to a lot post AND the user is logged in, tally
     * a `view` event into user_interests + recent_activity.
     */
    public static function maybe_record_lot_view($url, $email, $visitor_hash) {
        if (empty($email) || empty($url)) return;

        $post_id = url_to_postid($url);
        if (!$post_id) return;
        $post = get_post($post_id);
        if (!$post || $post->post_type !== 'lot') return;

        AF_User_Interests::record_view($email, $post_id);
    }

    /**
     * Hook handler — fires when an existing favourite AJAX endpoint records
     * a watchlist add. Email is already known from that AJAX path.
     */
    public static function record_lot_favorite($email, $post_id) {
        if (empty($email) || empty($post_id)) return;
        AF_User_Interests::record_favorite($email, (int) $post_id);
    }

    /**
     * Auto-create / migrate tables when the schema version on disk
     * (AF_Stats_Database::DB_VERSION) is newer than what's installed in
     * the DB. Runs on plugins_loaded — covers auto-update path because
     * register_activation_hook does not fire on update.
     *
     * Gated to is_admin() so frontend hits don't run dbDelta. Note that
     * is_admin() returns true for AJAX requests too, so the af_stats
     * AJAX endpoints will trigger the migration on the first call after
     * upgrade if an admin hasn't loaded wp-admin yet.
     */
    public static function maybe_create_tables() {
        if (!is_admin()) return;
        $installed = intval(get_option('af_stats_db_version', 0));
        if ($installed < AF_Stats_Database::DB_VERSION) {
            self::activate();
        }
    }

    /**
     * Run on plugin activation - create tables
     */
    public static function activate() {
        $dir = plugin_dir_path(__FILE__);
        $db_file = $dir . 'class-stats-database.php';
        if (!file_exists($db_file)) return;
        require_once $db_file;
        AF_Stats_Database::create_tables();
    }
}
