<?php

namespace AdvancedBlockControls;

// Exit if the file is accessed directly
if ( !defined('ABSPATH') ) {
    exit; 
}

class RegistrationManager
{
    private $charset_collate; // Declaring the property here

    const BLOCKS_TABLE_NAME = "abcon_blocks";

    const CONTROLS_TABLE_NAME = "abcon_controls";

    public function __construct()
    {
        global $wpdb;
        $this->charset_collate = $wpdb->get_charset_collate();
        $plugin_file = plugin_dir_path(dirname(__FILE__)) . 'advanced-block-controls.php';

        // Register activation hook for default options setup
        register_activation_hook($plugin_file, [$this, 'activate_plugin']);

         // Hook into the 'wpmu_new_blog' action to handle new site creation
         add_action('wpmu_new_blog', [$this, 'create_tables_for_new_site'], 10, 2);
    }

    public function create_tables_for_new_site($blog_id) {
        // Switch to the new site
        switch_to_blog($blog_id);

        // Set up options and create tables for the new site
        $this->setup_default_options();
        $this->create_custom_tables();

        // Setup default data for blocks and controls tables if they are empty
        if ($this->are_blocks_and_controls_tables_empty()) {
            $this->setup_default_data();
        }

        // Switch back to the original site
        restore_current_blog();
    }

    public function activate_plugin() {
        if (is_multisite()) {
            // Get all sites in the network
            $sites = get_sites();
            
            // Loop through each site
            foreach ($sites as $site) {
                // Switch to the site
                switch_to_blog($site->blog_id);

                // Set up options and create tables for this site
                $this->setup_default_options();
                $this->create_custom_tables();

                // Setup default data for blocks and controls tables if they are empty
                if ($this->are_blocks_and_controls_tables_empty()) {
                    $this->setup_default_data();
                }

                // Switch back to the original site
                restore_current_blog();
            }
        } else {
            // Single site activation
            $this->setup_default_options();
            $this->create_custom_tables();

            // Setup default data for blocks and controls tables if they are empty
            if ($this->are_blocks_and_controls_tables_empty()) {
                $this->setup_default_data();
            }
        }
    }

    public function setup_default_options()
    {
        $default_settings = array(
            'editor_specificity_core' => '',
            'editor_specificity_third_party' => '',
            'front_end_specificity_core' => '',
            'front_end_specificity_third_party' => '',
            'force_rules_core' => true,
            'force_rules_third_party' => true,
            'breakpoints' => array(
                'Tablet' =>  array(
                    'value' => '1024',
                    'unit' => 'px'
                ),
                'Mobile' => array(
                    'value' => '767',
                    'unit' => 'px'
                ),
            )
        );

        // General settings option
        add_option('abcon_settings', wp_json_encode($default_settings));

        // Deny list option
        add_option('abcon_deny_list', wp_json_encode(array()));

        // Upgrade version option
        add_option('abcon_upgrade_version', ABCON_VERSION);
    }

    public function create_custom_tables()
    {
        require_once(ABSPATH . 'wp-admin/includes/upgrade.php');

        global $wpdb;
        
        // Create blocks table only if it doesn't exist
        if (!$this->blocks_table_exists()) {
            // SQL for creating blocks table table
            $sql_blocks = "CREATE TABLE {$wpdb->prefix}" . self::BLOCKS_TABLE_NAME . " (
                id mediumint(9) NOT NULL AUTO_INCREMENT,
                block_name text NOT NULL,
                config text NOT NULL,
                is_default_settings boolean DEFAULT true,
                target text NOT NULL,
                date_added datetime DEFAULT CURRENT_TIMESTAMP,
                date_edited datetime DEFAULT NULL,
                PRIMARY KEY  (id)
            ) $this->charset_collate;";

            // Execute the SQL for blocks table
            dbDelta($sql_blocks);
        }

        // Check if the controls table exists
        if (!$this->controls_table_exists()) {
            // SQL for creating controls table
            // default_clone if this is a clone of the default control (happens when the control is opted out)
            $sql_controls = "CREATE TABLE {$wpdb->prefix}" . self::CONTROLS_TABLE_NAME . " (
                id mediumint(9) NOT NULL AUTO_INCREMENT,
                default_clone boolean,
                default_id mediumint(9), 
                blockId mediumint(9) NOT NULL,
                title text NOT NULL,
                type text NOT NULL,
                state text NOT NULL,
                target text NOT NULL,
                config text NOT NULL,
                order_num int NOT NULL DEFAULT 0,
                date_added datetime DEFAULT CURRENT_TIMESTAMP,
                date_edited datetime DEFAULT NULL,
                PRIMARY KEY  (id)
            ) {$this->charset_collate};";
            // Execute the SQL for controls table
            dbDelta($sql_controls);

            // Adding foreign keys seprately.
            $sql_add_fk = "ALTER TABLE {$wpdb->prefix}" . self::CONTROLS_TABLE_NAME . "
                ADD CONSTRAINT fk_blockId
                FOREIGN KEY (blockId)
                REFERENCES {$wpdb->prefix}" . self::BLOCKS_TABLE_NAME . "(id)
                ON DELETE CASCADE;";
            $wpdb->query($sql_add_fk); 
        }
    }

    // Setup default data for the plugin
    public static function setup_default_data() {
        global $wpdb;
        $table_prefix = $wpdb->prefix;
        $sql_file = dirname(__FILE__) . '/../initial-setup.sql';
        $sql = file_get_contents($sql_file);
    
        // Replace the placeholder with the actual table prefix
        $sql = str_replace('{prefix}_', $table_prefix, $sql);
    
        // Split the SQL file into individual queries
        $queries = explode(';', $sql);
        foreach ($queries as $query) {
            if (trim($query) != '') {
                $wpdb->query($query);
            }
        }
    }


    /**
     * Checks if the blocks table exists in the database.
     *
     * @return bool True if the table exists, false otherwise.
     */
    public function blocks_table_exists() {
        global $wpdb;

        $table_name = $wpdb->prefix . self::BLOCKS_TABLE_NAME;
        $query = $wpdb->prepare('SHOW TABLES LIKE %s', $wpdb->esc_like($table_name));

        if ($wpdb->get_var($query) == $table_name) {
            return true; // Table exists.
        } else {
            return false; // Table does not exist.
        }
    }

    /**
     * Checks if the controls table exists in the database.
     *
     * @return bool True if the table exists, false otherwise.
     */
    public function controls_table_exists() {
        global $wpdb;

        $table_name = $wpdb->prefix . self::CONTROLS_TABLE_NAME;
        $query = $wpdb->prepare('SHOW TABLES LIKE %s', $wpdb->esc_like($table_name));

        if ($wpdb->get_var($query) == $table_name) {
            return true; // Table exists.
        } else {
            return false; // Table does not exist.
        }
    }

    /**
     * Checks if the blocks and controls tables are empty.
     *
     * @return bool True if both tables are empty, false otherwise.
     */
    public function are_blocks_and_controls_tables_empty() {
        global $wpdb;

        $blocks_table_name = $wpdb->prefix . self::BLOCKS_TABLE_NAME;
        $controls_table_name = $wpdb->prefix . self::CONTROLS_TABLE_NAME;

        $blocks_query = "SELECT COUNT(*) FROM {$blocks_table_name}";
        $controls_query = "SELECT COUNT(*) FROM {$controls_table_name}";

        $blocks_count = $wpdb->get_var($blocks_query);
        $controls_count = $wpdb->get_var($controls_query);

        return $blocks_count == 0 && $controls_count == 0;
    }

     // Reset Control Settings
     public function reset_control_settings() {
        global $wpdb;
    
        // Empty the tables 
        $wpdb->query("DELETE FROM {$wpdb->prefix}" . self::CONTROLS_TABLE_NAME);
        $wpdb->query("DELETE FROM {$wpdb->prefix}" . self::BLOCKS_TABLE_NAME);
    
        // Re-import the default data
        $this->setup_default_data();
    
        // Reset the deny list option
        update_option('abcon_deny_list', wp_json_encode(array()));
    
        return true;
    }

    // Esport control settings
    public function export_control_settings() {
        global $wpdb;
    
        // Fetch blocks
        $blocks = $wpdb->get_results(
            "SELECT * FROM {$wpdb->prefix}" . self::BLOCKS_TABLE_NAME,
            ARRAY_A
        );
    
        // Fetch controls
        $controls = $wpdb->get_results(
            "SELECT * FROM {$wpdb->prefix}" . self::CONTROLS_TABLE_NAME,
            ARRAY_A
        );
    
        // Fetch deny list
        $deny_list_option = get_option('abcon_deny_list');
        $deny_list = json_decode($deny_list_option, true);
    
        // Pack into a single array
        $exportData = [
            'blocks' => $blocks,
            'controls' => $controls,
            'deny_list' => $deny_list,
        ];
    
        return $exportData;
    }


    // Handle import control settings
    public function import_control_settings($importData) {
        global $wpdb;
    
        // Validate structure first
        if (
            !isset($importData['blocks']) || !is_array($importData['blocks']) ||
            !isset($importData['controls']) || !is_array($importData['controls']) ||
            !isset($importData['deny_list']) || !is_array($importData['deny_list'])
        ) {
            throw new \Exception('Invalid import file structure.');
        }
    
        // Start transaction
        $wpdb->query('START TRANSACTION');
    
        try {
            // Clear existing tables
            $wpdb->query("DELETE FROM {$wpdb->prefix}" . self::CONTROLS_TABLE_NAME);
            $wpdb->query("DELETE FROM {$wpdb->prefix}" . self::BLOCKS_TABLE_NAME);
    
            // Insert blocks
            foreach ($importData['blocks'] as $block) {
                $wpdb->insert(
                    "{$wpdb->prefix}" . self::BLOCKS_TABLE_NAME,
                    [
                        'id' => $block['id'],
                        'block_name' => sanitize_text_field($block['block_name']),
                        'config' => maybe_serialize($block['config']),
                        'is_default_settings' => intval($block['is_default_settings']),
                        'target' => maybe_serialize($block['target']),
                        'date_added' => $block['date_added'],
                        'date_edited' => $block['date_edited'],
                    ]
                );
            }
    
            // Insert controls
            foreach ($importData['controls'] as $control) {
                $wpdb->insert(
                    "{$wpdb->prefix}" . self::CONTROLS_TABLE_NAME,
                    [
                        'id' => $control['id'],
                        'default_clone' => intval($control['default_clone']),
                        'default_id' => $control['default_id'],
                        'blockId' => intval($control['blockId']),
                        'title' => sanitize_text_field($control['title']),
                        'type' => sanitize_text_field($control['type']),
                        'state' => sanitize_text_field($control['state']),
                        'target' => maybe_serialize($control['target']),
                        'config' => maybe_serialize($control['config']),
                        'order_num' => intval($control['order_num']),
                        'date_added' => $control['date_added'],
                        'date_edited' => $control['date_edited'],
                    ]
                );
            }
    
            // Update deny list
            update_option('abcon_deny_list', wp_json_encode($importData['deny_list']));
    
            // Commit transaction
            $wpdb->query('COMMIT');
    
            return true;
        } catch (\Exception $e) {
            $wpdb->query('ROLLBACK');
            throw $e;
        }
    }

}
