<?php

/**
 * Core plugin class with optimized initialization and error handling
 *
 * @package ContentPerformanceAnalyzer
 * @since 1.0.0
 */
// Prevent direct access
if ( !defined( 'ABSPATH' ) ) {
    exit;
}
class CPAP_Core {
    /**
     * Singleton instance
     */
    private static $instance = null;

    /**
     * Component instances
     */
    private $admin = null;

    private $data_collector = null;

    private $ai_processor = null;

    private $batch_processor = null;

    private $internal_links = null;

    /**
     * Get singleton instance
     */
    public static function get_instance() {
        if ( null === self::$instance ) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    /**
     * Constructor
     */
    private function __construct() {
        // Private constructor for singleton
    }

    /**
     * Initialize the plugin
     */
    public function init() {
        // Load components only when needed
        add_action( 'init', array($this, 'load_components'), 0 );
        // Schedule tasks on appropriate hooks
        add_action( 'init', array($this, 'setup_cron_schedules') );
        // Handle upgrades. Hooked to init as well as admin_init because cron
        // requests never fire admin_init: after an overnight auto-update the
        // daily-refresh cron can run (and try to write snapshots) before any
        // admin visits wp-admin, so upgrade steps must also run in cron
        // context. The version_compare guard makes the second call a no-op.
        add_action( 'init', array($this, 'check_plugin_upgrade') );
        add_action( 'admin_init', array($this, 'check_plugin_upgrade') );
        // Check if we need to auto-start data collection after activation
        add_action( 'admin_init', array($this, 'auto_start_data_collection'), 5 );
        // Add custom cron intervals
        add_filter( 'cron_schedules', array($this, 'add_cron_intervals') );
    }

    /**
     * Load components based on context
     */
    public function load_components() {
        // Always load core functions
        $this->load_core_components();
        // Load admin components only in admin area
        if ( is_admin() ) {
            $this->load_admin_components();
        }
        // Load batch processor only when needed
        if ( $this->should_load_batch_processor() ) {
            $this->load_batch_processor();
        }
    }

    /**
     * Load core components
     */
    private function load_core_components() {
        // Data collector - needed for cron jobs
        if ( !$this->data_collector ) {
            $this->data_collector = new CPAP_Data_Collector();
            $this->data_collector->init();
        }
        // Load Serper collector — required before AI processor
        if ( !class_exists( 'CPAP_Serper_Collector' ) ) {
            require_once CPANALYZER_PLUGIN_DIR . 'includes/class-cpa-serper-collector.php';
        }
        // AI processor - loaded on demand
        if ( !$this->ai_processor ) {
            $this->ai_processor = new CPAP_AI_Processor();
            $this->ai_processor->init();
        }
    }

    /**
     * Load admin components
     */
    private function load_admin_components() {
        if ( !$this->admin && current_user_can( 'manage_options' ) ) {
            $this->admin = new CPAP_Admin();
            $this->admin->init();
        }
        // Load internal links component in admin
        if ( !$this->internal_links && current_user_can( 'manage_options' ) ) {
            $this->internal_links = new CPAP_Internal_Links();
            $this->internal_links->init();
        }
    }

    /**
     * Check if batch processor should be loaded
     */
    private function should_load_batch_processor() {
        // Load if in admin or if batch processing is scheduled
        return is_admin() || wp_next_scheduled( 'cpanalyzer_batch_process' ) || wp_doing_cron() || wp_doing_ajax();
    }

    /**
     * Load batch processor
     */
    private function load_batch_processor() {
        if ( !$this->batch_processor ) {
            // Only include file if not already loaded
            if ( !class_exists( 'CPAP_Batch_Processor' ) ) {
                require_once CPANALYZER_PLUGIN_DIR . 'includes/class-cpa-batch-processor.php';
            }
            $this->batch_processor = new CPAP_Batch_Processor();
            $this->batch_processor->init();
        }
    }

    /**
     * Setup cron schedules (runs once on init)
     */
    public function setup_cron_schedules() {
        // Daily refresh - only schedule if not already scheduled
        if ( !wp_next_scheduled( 'cpanalyzer_daily_refresh' ) ) {
            $this->schedule_daily_refresh();
        }
        // Off-peak scan - only schedule if not already scheduled
        if ( !wp_next_scheduled( 'cpanalyzer_off_peak_scan' ) ) {
            $this->schedule_off_peak_scan();
        }
        // Clean up stuck processes (safety mechanism)
        if ( !wp_next_scheduled( 'cpanalyzer_cleanup_stuck_processes' ) ) {
            wp_schedule_event( time(), 'hourly', 'cpanalyzer_cleanup_stuck_processes' );
        }
        // Add cleanup action
        add_action( 'cpanalyzer_cleanup_stuck_processes', array($this, 'cleanup_stuck_processes') );
        // Add internal links processing action
        add_action( 'cpanalyzer_process_link_analysis', array($this, 'process_link_analysis') );
    }

    /**
     * Add custom cron intervals
     */
    public function add_cron_intervals( $schedules ) {
        $schedules['every_5_minutes'] = array(
            'interval' => 300,
            'display'  => __( 'Every 5 Minutes', 'content-performance-analyzer' ),
        );
        $schedules['every_30_minutes'] = array(
            'interval' => 1800,
            'display'  => __( 'Every 30 Minutes', 'content-performance-analyzer' ),
        );
        return $schedules;
    }

    /**
     * Schedule daily refresh
     */
    private function schedule_daily_refresh() {
        $timestamp = strtotime( 'tomorrow midnight' );
        wp_schedule_event( $timestamp, 'daily', 'cpanalyzer_daily_refresh' );
    }

    /**
     * Schedule off-peak scan
     */
    private function schedule_off_peak_scan() {
        // Get user-configured time or default to 2 AM in the site timezone
        $hour = get_option( 'cpanalyzer_off_peak_hour', 2 );
        $timezone = get_option( 'cpanalyzer_off_peak_timezone', wp_timezone_string() );
        // Calculate next occurrence
        $dt = new DateTime('now', new DateTimeZone($timezone));
        $dt->setTime( $hour, 0, 0 );
        // If time has passed today, schedule for tomorrow
        if ( $dt->getTimestamp() < time() ) {
            $dt->modify( '+1 day' );
        }
        wp_schedule_event( $dt->getTimestamp(), 'daily', 'cpanalyzer_off_peak_scan' );
    }

    /**
     * Cleanup stuck processes
     */
    public function cleanup_stuck_processes() {
        global $wpdb;
        $cpanalyzer_urls_table = self::get_urls_table_name();
        // Reset URLs stuck in 'in_progress' for more than 10 minutes
        $ten_minutes_ago = gmdate( 'Y-m-d H:i:s', strtotime( '-10 minutes' ) );
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQLPlaceholders.UnsupportedIdentifierPlaceholder -- Custom table cleanup with %i placeholder (requires WP 6.2+, our minimum version)
        $stuck_count = $wpdb->query( $wpdb->prepare( "UPDATE %i\n             SET status = 'pending',\n                 error_message = 'Process timeout - automatically reset'\n             WHERE status = 'in_progress'\n             AND updated_at < %s", $cpanalyzer_urls_table, $ten_minutes_ago ) );
        if ( $stuck_count > 0 ) {
            // Log the cleanup
            $this->log_event( 'cleanup_stuck_processes', sprintf( 'Reset %d stuck URLs', $stuck_count ) );
        }
        // Also clear stuck batch running flag
        $batch_running = get_transient( 'cpanalyzer_batch_running' );
        $batch_timestamp = get_transient( 'cpanalyzer_batch_timestamp' );
        if ( $batch_running && $batch_timestamp && time() - $batch_timestamp > 600 ) {
            delete_transient( 'cpanalyzer_batch_running' );
            delete_transient( 'cpanalyzer_batch_timestamp' );
            $this->log_event( 'cleanup_stuck_batch', 'Cleared stuck batch processing flag' );
        }
    }

    /**
     * Auto-start data collection after activation if settings are configured
     */
    public function auto_start_data_collection() {
        // Only run in admin area for users with manage_options capability
        if ( !is_admin() || !current_user_can( 'manage_options' ) ) {
            return;
        }
        // Check if we have a trigger flag from activation
        $trigger_flag = get_option( 'cpanalyzer_trigger_collection_on_load', 'no' );
        if ( $trigger_flag === 'yes' ) {
            // Clear the flag first
            delete_option( 'cpanalyzer_trigger_collection_on_load' );
            // Check if settings are configured
            $oauth = new CPAP_Google_OAuth();
            $property_id = get_option( 'cpanalyzer_property_id', '' );
            $site_url = get_option( 'cpanalyzer_site_url', '' );
            if ( $oauth->is_connected() && !empty( $property_id ) && !empty( $site_url ) ) {
                // Only trigger if not already running
                if ( !wp_next_scheduled( 'cpanalyzer_daily_refresh' ) && !get_transient( 'cpanalyzer_batch_running' ) ) {
                    // Schedule immediate data collection
                    wp_schedule_single_event( time() + 5, 'cpanalyzer_daily_refresh' );
                    update_option( 'cpanalyzer_status_msg', __( 'Auto-starting data collection after plugin activation...', 'content-performance-analyzer' ) );
                    // Log the auto-start
                    $this->log_event( 'auto_start', 'Automatically starting data collection after activation' );
                }
            }
        }
    }

    /**
     * Check for plugin upgrades
     */
    public function check_plugin_upgrade() {
        $current_version = get_option( 'cpanalyzer_version', '0' );
        if ( version_compare( $current_version, CPANALYZER_VERSION, '<' ) ) {
            $this->run_upgrade( $current_version );
        }
    }

    /**
     * Run upgrade routines
     */
    private function run_upgrade( $from_version ) {
        // Version-specific upgrades
        if ( version_compare( $from_version, '1.0.0', '<' ) ) {
            $this->upgrade_to_100();
        }
        if ( version_compare( $from_version, '1.4.5', '<' ) ) {
            self::create_tables();
        }
        if ( version_compare( $from_version, '1.4.7', '<' ) ) {
            self::create_tables();
            if ( class_exists( 'CPAP_Artifacts' ) ) {
                CPAP_Artifacts::migrate_from_page_actions();
            }
        }
        // Update version
        update_option( 'cpanalyzer_version', CPANALYZER_VERSION );
        // Log upgrade
        $this->log_event( 'plugin_upgrade', sprintf( 'Upgraded from %s to %s', $from_version, CPANALYZER_VERSION ) );
    }

    /**
     * Upgrade to version 1.0.0
     */
    private function upgrade_to_100() {
        // Ensure tables exist or are updated
        self::create_tables();
        // Migrate any old data if needed
        $this->migrate_old_data();
    }

    /**
     * Migrate old data to new structure
     */
    private function migrate_old_data() {
        // Check if migration is needed
        if ( get_option( 'cpanalyzer_data_migrated_180', false ) ) {
            return;
        }
        // Perform migration (example)
        // This would migrate data from old options to new table structure
        update_option( 'cpanalyzer_data_migrated_180', true );
    }

    /**
     * Plugin activation
     */
    public static function activate() {
        // Check PHP version
        if ( version_compare( PHP_VERSION, '7.4', '<' ) ) {
            deactivate_plugins( plugin_basename( CPANALYZER_PLUGIN_FILE ) );
            wp_die( esc_html__( 'Content Performance Analyzer requires PHP 7.4 or higher.', 'content-performance-analyzer' ), esc_html__( 'Plugin Activation Error', 'content-performance-analyzer' ), array(
                'back_link' => true,
            ) );
        }
        // Check WordPress version
        if ( version_compare( get_bloginfo( 'version' ), '6.2', '<' ) ) {
            deactivate_plugins( plugin_basename( CPANALYZER_PLUGIN_FILE ) );
            wp_die( esc_html__( 'Content Performance Analyzer requires WordPress 6.2 or higher.', 'content-performance-analyzer' ), esc_html__( 'Plugin Activation Error', 'content-performance-analyzer' ), array(
                'back_link' => true,
            ) );
        }
        // Create database tables
        $table_created = self::create_tables();
        if ( !$table_created ) {
            deactivate_plugins( plugin_basename( CPANALYZER_PLUGIN_FILE ) );
            wp_die( esc_html__( 'Failed to create database tables. Please check database permissions.', 'content-performance-analyzer' ), esc_html__( 'Plugin Activation Error', 'content-performance-analyzer' ), array(
                'back_link' => true,
            ) );
        }
        // Set default options
        self::set_default_options();
        // Schedule cron jobs (will be properly scheduled on next page load)
        // Not scheduling here to avoid duplicate events
        // Schedule initial data collection after activation
        if ( !wp_next_scheduled( 'cpanalyzer_daily_refresh' ) ) {
            wp_schedule_single_event( time() + 10, 'cpanalyzer_daily_refresh' );
        }
        // Also check if we can immediately start data collection
        self::check_immediate_start();
        // Clear any existing caches
        wp_cache_flush();
        // Flush rewrite rules
        flush_rewrite_rules();
    }

    /**
     * Plugin deactivation
     */
    public static function deactivate() {
        // Clear scheduled hooks
        $cron_events = array(
            'cpanalyzer_daily_refresh',
            'cpanalyzer_off_peak_scan',
            'cpanalyzer_batch_process',
            'cpanalyzer_cleanup_stuck_processes',
            // These three were previously left scheduled on deactivate,
            // so a deactivate/reactivate cycle orphaned their events.
            'cpanalyzer_ai_drain',
            'cpanalyzer_background_content_analysis',
            'cpanalyzer_process_link_analysis',
        );
        foreach ( $cron_events as $event ) {
            wp_clear_scheduled_hook( $event );
        }
        // Clear transients
        delete_transient( 'cpanalyzer_batch_running' );
        delete_transient( 'cpanalyzer_batch_timestamp' );
        // Update batch status
        update_option( 'cpanalyzer_batch_status', 'stopped' );
        // Reset any in-progress URLs to pending
        global $wpdb;
        $cpanalyzer_urls_table = self::get_urls_table_name();
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Table existence check for cleanup
        if ( $wpdb->get_var( $wpdb->prepare( "SHOW TABLES LIKE %s", $cpanalyzer_urls_table ) ) === $cpanalyzer_urls_table ) {
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Reset stuck processes on activation
            $wpdb->update( $cpanalyzer_urls_table, array(
                'status' => 'pending',
            ), array(
                'status' => 'in_progress',
            ) );
        }
        // Flush rewrite rules
        flush_rewrite_rules();
    }

    /**
     * Create database tables with proper error handling
     */
    private static function create_tables() {
        global $wpdb;
        $cpanalyzer_urls_table = esc_sql( self::get_urls_table_name() );
        $cpanalyzer_snapshots_table = esc_sql( self::get_snapshots_table_name() );
        $charset_collate = $wpdb->get_charset_collate();
        $sql = "CREATE TABLE IF NOT EXISTS {$cpanalyzer_urls_table} (\n            id INT AUTO_INCREMENT PRIMARY KEY,\n            url VARCHAR(255) NOT NULL,\n            status ENUM('pending','in_progress','success','failed') DEFAULT 'pending',\n            last_scanned DATETIME DEFAULT NULL,\n            scan_result LONGTEXT DEFAULT NULL,\n            error_message TEXT DEFAULT NULL,\n            ga_data LONGTEXT DEFAULT NULL,\n            gsc_data LONGTEXT DEFAULT NULL,\n            content_data LONGTEXT DEFAULT NULL,\n            ai_suggestions LONGTEXT DEFAULT NULL,\n            retry_count INT DEFAULT 0,\n            priority INT DEFAULT 0,\n            created_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n            updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\n            UNIQUE KEY url_unique (url),\n            KEY status_idx (status),\n            KEY last_scanned_idx (last_scanned),\n            KEY priority_idx (priority),\n            KEY status_priority_idx (status, priority)\n        ) {$charset_collate};";
        $snapshots_sql = "CREATE TABLE IF NOT EXISTS {$cpanalyzer_snapshots_table} (\n            id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,\n            url_hash CHAR(32) NOT NULL,\n            url TEXT NOT NULL,\n            week_start DATE NOT NULL,\n            clicks INT NULL,\n            impressions INT NULL,\n            ctr DECIMAL(7,4) NULL,\n            position DECIMAL(7,2) NULL,\n            views INT NULL,\n            engagement_rate DECIMAL(7,4) NULL,\n            conversions INT NULL,\n            flag VARCHAR(20) NULL,\n            decay_type VARCHAR(40) NULL,\n            aeo_score TINYINT UNSIGNED NULL,\n            captured_at DATETIME NOT NULL,\n            PRIMARY KEY  (id),\n            UNIQUE KEY url_week (url_hash, week_start),\n            KEY week_start (week_start)\n        ) {$charset_collate};";
        require_once ABSPATH . 'wp-admin/includes/upgrade.php';
        // Suppress errors and capture them
        $wpdb->suppress_errors();
        dbDelta( $sql );
        dbDelta( $snapshots_sql );
        $wpdb->suppress_errors( false );
        // Check if table was created successfully
        if ( $wpdb->last_error ) {
            // Log error using error_log since we're in static context
            if ( defined( 'WP_DEBUG_LOG' ) && WP_DEBUG_LOG ) {
                // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- Static context error logging
                error_log( '[CPA] Table Creation Error: ' . $wpdb->last_error );
            }
            return false;
        }
        // Verify table exists
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Table existence verification after creation
        $table_exists = $wpdb->get_var( $wpdb->prepare( "SHOW TABLES LIKE %s", $cpanalyzer_urls_table ) ) === $cpanalyzer_urls_table;
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Table existence verification after creation
        $snapshots_table_exists = $wpdb->get_var( $wpdb->prepare( "SHOW TABLES LIKE %s", $cpanalyzer_snapshots_table ) ) === $cpanalyzer_snapshots_table;
        $artifacts_table_exists = true;
        if ( $table_exists && $snapshots_table_exists && $artifacts_table_exists ) {
            update_option( 'cpanalyzer_db_version', '1.4.7' );
            return true;
        }
        return false;
    }

    /**
     * Set default options with validation
     */
    private static function set_default_options() {
        $default_options = array(
            'cpanalyzer_openai_key'          => '',
            'cpanalyzer_property_id'         => '',
            'cpanalyzer_site_url'            => '',
            'cpanalyzer_oauth_client_id'     => '',
            'cpanalyzer_oauth_client_secret' => '',
            'cpanalyzer_version'             => CPANALYZER_VERSION,
            'cpanalyzer_batch_size'          => 10,
            'cpanalyzer_off_peak_hour'       => 2,
            'cpanalyzer_off_peak_timezone'   => wp_timezone_string(),
            'cpanalyzer_max_retries'         => 3,
            'cpanalyzer_enable_auto_scan'    => 'no',
            'cpanalyzer_max_execution_time'  => 25,
            'cpanalyzer_content_chunk_size'  => 2000,
            'cpanalyzer_log_errors'          => 'yes',
            'cpanalyzer_debug_mode'          => 'no',
        );
        foreach ( $default_options as $option => $value ) {
            if ( get_option( $option ) === false ) {
                add_option( $option, $value );
            }
        }
        // Set installation date if not set
        if ( !get_option( 'cpanalyzer_install_date' ) ) {
            add_option( 'cpanalyzer_install_date', current_time( 'mysql' ) );
        }
    }

    /**
     * Log events for debugging
     * Changed from private to public to allow access from other classes
     */
    public function log_event( $event_type, $message, $data = array() ) {
        if ( get_option( 'cpanalyzer_log_errors', 'yes' ) !== 'yes' ) {
            return;
        }
        $log_entry = array(
            'timestamp' => current_time( 'mysql' ),
            'event'     => $event_type,
            'message'   => $message,
            'data'      => $data,
        );
        // Store in transient for recent logs (keep last 100 entries)
        $logs = ( get_transient( 'cpanalyzer_event_logs' ) ?: array() );
        array_unshift( $logs, $log_entry );
        $logs = array_slice( $logs, 0, 100 );
        set_transient( 'cpanalyzer_event_logs', $logs, DAY_IN_SECONDS );
        // Also log to error_log if debug mode is on
        if ( get_option( 'cpanalyzer_debug_mode', 'no' ) === 'yes' && defined( 'WP_DEBUG_LOG' ) && WP_DEBUG_LOG ) {
            // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- Protected debug logging
            error_log( sprintf( '[CPA] %s: %s', $event_type, $message ) );
        }
    }

    /**
     * Check if we can immediately start data collection during activation
     */
    private static function check_immediate_start() {
        // Check if settings are configured
        $oauth = new CPAP_Google_OAuth();
        $property_id = get_option( 'cpanalyzer_property_id', '' );
        $site_url = get_option( 'cpanalyzer_site_url', '' );
        if ( $oauth->is_connected() && !empty( $property_id ) && !empty( $site_url ) ) {
            // Set a flag to trigger data collection on next admin load
            update_option( 'cpanalyzer_trigger_collection_on_load', 'yes' );
            update_option( 'cpanalyzer_status_msg', __( 'Data collection will start automatically...', 'content-performance-analyzer' ) );
        }
    }

    /**
     * Process internal links analysis in background
     */
    public function process_link_analysis() {
        $posts = get_option( 'cpanalyzer_posts_for_link_analysis', array() );
        if ( empty( $posts ) ) {
            return;
        }
        // Load internal links class if not loaded
        if ( !$this->internal_links ) {
            $this->internal_links = new CPAP_Internal_Links();
        }
        // Run the analysis
        $this->internal_links->analyze_linking_opportunities( $posts );
        // Clean up
        delete_option( 'cpanalyzer_posts_for_link_analysis' );
    }

    /**
     * Get component instance
     */
    public function get_component( $component ) {
        switch ( $component ) {
            case 'admin':
                return $this->admin;
            case 'data_collector':
                return $this->data_collector;
            case 'ai_processor':
                return $this->ai_processor;
            case 'batch_processor':
                return $this->batch_processor;
            case 'internal_links':
                return $this->internal_links;
            default:
                return null;
        }
    }

    /**
     * Get sanitized reference to plugin's URLs table.
     *
     * @return string
     */
    private static function get_urls_table_name() {
        global $wpdb;
        return $wpdb->prefix . 'cpanalyzer_urls';
    }

    private static function get_snapshots_table_name() {
        global $wpdb;
        return $wpdb->prefix . 'cpanalyzer_snapshots';
    }

    private static function get_sanitized_urls_table_name() {
        return esc_sql( self::get_urls_table_name() );
    }

}
