<?php
if (!defined('ABSPATH'))
    exit;

class ASSI_Loader {

    public $blogUserData = null;
    public $showConnectionNotice = false;
    public $blogLanguage = 'en_US';

    public function __construct() {
        if (is_admin()) {
            $this->blogLanguage = get_locale();
            $this->call_backend_hooks();
        }
    }

    public function call_backend_hooks() {

        require_once(ASSI_PLUGIN_DIR . 'includes/Ajax/Post.php');
        require_once(ASSI_PLUGIN_DIR . 'includes/Ajax/Get.php');
        require_once(ASSI_PLUGIN_DIR . 'includes/Tools.php');
        require_once(ASSI_PLUGIN_DIR . 'includes/Request.php');
        require_once(ASSI_PLUGIN_DIR . 'includes/Heartbeat.php');
        require_once(ASSI_PLUGIN_DIR . 'includes/Notification.php');
        require_once(ASSI_PLUGIN_DIR . 'includes/History.php');
        require_once(ASSI_PLUGIN_DIR . 'includes/Sidebar.php');
        require_once(ASSI_PLUGIN_DIR . 'assets/lib/markdown/Parsedown.php');

        ASSI_Ajax_Get::getInstance();
        ASSI_Ajax_Post::getInstance();

        register_deactivation_hook(__FILE__, array($this, 'deactivatePlugin'));
        add_action('admin_init', array($this, 'registerAssets'));
        add_action('admin_menu', array($this, 'createMenu'));
        add_action('admin_bar_menu', array($this, 'createToolbarMenu'), 94);
        add_action('init', array($this, 'defineCurrentUserId'));
        add_action('admin_notices', array($this, 'initNotices'));
        add_action('init', array($this, 'startHeartbeat'));
        add_filter('post_row_actions', array($this, 'assAddCustomContentAction'), 100, 2);
        add_filter('page_row_actions', array($this, 'assAddCustomContentAction'), 100, 2);
        add_action('admin_footer-edit.php', array($this, 'assAddCustomContentTopButton'));
        add_action('enqueue_block_editor_assets', array($this, 'initEditorSidebar'));
        add_action('admin_enqueue_scripts', array($this, 'initClassicEditorSidebar'));
        
        // last position important
        add_action('plugins_loaded', array($this, 'checkForUpdate'));
    }

    public function defineCurrentUserId() {
        define('ASSI_PLUGIN_BLOG_USER_ID', get_current_user_id());
        if ((int) ASSI_PLUGIN_BLOG_USER_ID > 0) {
            $this->blogUserData = get_userdata(ASSI_PLUGIN_BLOG_USER_ID);
            $this->getToken();
        }
    }

    public function assAddCustomContentAction($actions, $post) {
        $assCustomUrl = admin_url('post.php?post=' . $post->ID . '&action=edit&ass-ai-editor=open');
        $assAction = array('assi_ai_editor' => '<a href="' . esc_url($assCustomUrl) . '" class="assi-ai-action">' . __('Edit with Assistini (AI Editor)', 'assistini') . '</a>');
        return $assAction + $actions;
    }

    function assAddCustomContentTopButton() {
        $screen = get_current_screen();
        if ($screen && $screen->post_type === 'post') {
            $assCustomBtnUrl = admin_url('post-new.php?ass-ai-editor=open');
        } else {
            $assCustomBtnUrl = admin_url('post-new.php');
            $assCustomBtnUrl = add_query_arg(
                    array(
                        'post_type' => $screen->post_type,
                        'ass-ai-editor' => 'open',
                    ),
                    $assCustomBtnUrl
            );
        }
        ?>
        <script type="text/javascript">
            jQuery(document).ready(function ($) {
                const aiButton = $('<a>', {
                    class: 'page-title-action assi-ai-button',
                    href: <?php echo wp_json_encode($assCustomBtnUrl); ?>,
                    text: '<?php esc_html_e('Add Content with Assitini (AI Editor)', 'assistini') ?>',
                });

                $('.page-title-action').last().after(aiButton);
            });
        </script>
        <style>
            .assi-ai-button {
                margin-left: 8px;
            }
        </style>
        <?php
    }

    public function startHeartbeat() {
        add_filter('heartbeat_received', array(ASSI_Heartbeat::getInstance(), 'init'), 10, 2);
    }

    public function assistini_set_heartbeat_interval($settings) {
        $screen = get_current_screen();
        if ($screen && $screen->id === 'toplevel_page_assistini') {
            $settings['interval'] = 45;
        }
        return $settings;
    }

    public function registerAssets() {
        //CSS
        wp_register_style('ASSIBOOTSTRAPCSS', plugins_url('assets/lib/bootstrap/bootstrap.min.css', ASSI_PLUGIN_FILE), array(), ASSI_PLUGIN_VERSION);
        wp_register_style('ASSIBOOTSTRAPICONSCSS', plugins_url('assets/lib/bootstrap/bootstrap-icons.min.css', ASSI_PLUGIN_FILE), array(), ASSI_PLUGIN_VERSION);
        wp_register_style('ASSIROOTCSS', plugins_url('assets/css/general.css', ASSI_PLUGIN_FILE), array(), ASSI_PLUGIN_VERSION);
        wp_register_style('ASSIEDITORSIDEBARCSS', plugins_url('assets/css/editor_sidebar.css', ASSI_PLUGIN_FILE), array(), ASSI_PLUGIN_VERSION);
        wp_register_style('ASSICOLORSCSS', plugins_url('assets/css/custom_colors.css', ASSI_PLUGIN_FILE), array(), ASSI_PLUGIN_VERSION);
        wp_register_style('ASSIFONTPOPPINSCSS', plugins_url('assets/css/fonts/poppins.css', ASSI_PLUGIN_FILE), array(), ASSI_PLUGIN_VERSION);
        wp_register_style('ASSIFONTNUNITOCSS', plugins_url('assets/css/fonts/nunito.css', ASSI_PLUGIN_FILE), array(), ASSI_PLUGIN_VERSION);
        //JS
        wp_register_script('ASSIBOOTSTRAPJS', plugins_url('assets/lib/bootstrap/bootstrap.bundle.min.js', ASSI_PLUGIN_FILE), array(), ASSI_PLUGIN_VERSION, true);
        wp_register_script('ASSIMARKDOWNJS', plugins_url('assets/lib/markdown/marked.min.js', ASSI_PLUGIN_FILE), array(), ASSI_PLUGIN_VERSION, true);
        wp_register_script('ASSICIRCLEPROGRESSJS', plugins_url('assets/lib/circle/circle-progress.js', ASSI_PLUGIN_FILE), array(), ASSI_PLUGIN_VERSION, true);
        wp_register_script('ASSIROOTJS', plugins_url('assets/js/general.js', ASSI_PLUGIN_FILE), array('wp-i18n'), ASSI_PLUGIN_VERSION, true);
        wp_register_script('ASSIEDITORSIDEBARJS', plugins_url('assets/js/editor/sidebar.js', ASSI_PLUGIN_FILE), array('wp-plugins', 'wp-element', 'wp-blocks', 'wp-rich-text', 'wp-editor', 'wp-components', 'wp-compose', 'wp-data'), ASSI_PLUGIN_VERSION, true);
    }

    public function getToken() {
        $blogAccessToken = get_option('ASSI_PLUGIN_BLOG_ACCESS_TOKEN');
        define('ASSI_PLUGIN_CONNECTION_TO_SERVER', ((int) get_option('ASSI_PLUGIN_CONNECTION_TO_SERVER') == 1 ? true : false));
        $blogUserToken = '';
        $accountPlan = get_option('ASSI_PLUGIN_ACCOUNT');
        if ($accountPlan == false) {
            $accountPlan = array();
        }

        global $wpdb;
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
        $userExist = $wpdb->get_row($wpdb->prepare("SELECT blog_user_token FROM `{$wpdb->prefix}assi_user` WHERE `blog_user_id` = %d", $this->blogUserData->ID));
        if (empty($userExist) || !isset($userExist->blog_user_token) || empty($userExist->blog_user_token) || !isset($blogAccessToken) || empty($blogAccessToken)) {
            $postData = array('blog_identifier' => hash('sha256', get_current_blog_id() . get_option('admin_email') . get_option('siteurl')), 'blog_user_id' => $this->blogUserData->ID, 'blog_url' => get_option('siteurl'));
            $result = ASSI_Request::post(ASSI_PLUGIN_API_WP_ENDPOINT . 'user/token/add', $postData);
            if (isset($result->status) && $result->status == 'success' && isset($result->blog_user_token) && !empty($result->blog_user_token)) {
                $blogUserToken = $result->blog_user_token;
                if (isset($result->blog_access_token) && !empty($result->blog_access_token)) {
                    update_option('ASSI_PLUGIN_BLOG_ACCESS_TOKEN', sanitize_text_field($result->blog_access_token), false);
                }
                // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
                $wpdb->query($wpdb->prepare("INSERT INTO `{$wpdb->prefix}assi_user` (`blog_user_token`, `blog_user_id`, `register_date`) VALUES (%s,%d,%s);", $result->blog_user_token, (int) $this->blogUserData->ID, gmdate('Y-m-d H:i:s')));

                $accountPlan['plan']['plan_id'] = (isset($result->user_data->plan_id) ? (int) $result->user_data->plan_id : 0);
                $accountPlan['plan']['credits_open'] = (isset($result->user_data->ass_words_open) ? (int) $result->user_data->ass_words_open : 0);
                $accountPlan['plan']['credits_total'] = (isset($result->user_data->ass_words_total) ? (int) $result->user_data->ass_words_total : 0);
                $accountPlan['plan']['max_chats'] = (isset($result->user_data->ass_plan_max_count_chats) ? (int) $result->user_data->ass_plan_max_count_chats : 0);
                $accountPlan['plan']['max_templates'] = (isset($result->user_data->ass_plan_max_count_template) ? (int) $result->user_data->ass_plan_max_count_template : 0);
                $accountPlan['plan']['addons']['normal']['credits_open'] = (isset($result->user_data->ass_addon_quota->normal->open_quota) ? (int) $result->user_data->ass_addon_quota->normal->open_quota : 0);
                $accountPlan['plan']['addons']['normal']['credits_total'] = (isset($result->user_data->ass_addon_quota->normal->max_quota) ? (int) $result->user_data->ass_addon_quota->normal->max_quota : 0);
                $accountPlan['plan']['addons']['promotion']['credits_open'] = (isset($result->user_data->ass_addon_quota->promotion->open_quota) ? (int) $result->user_data->ass_addon_quota->promotion->open_quota : 0);
                $accountPlan['plan']['addons']['promotion']['credits_total'] = (isset($result->user_data->ass_addon_quota->promotion->max_quota) ? (int) $result->user_data->ass_addon_quota->promotion->max_quota : 0);
                $accountPlan['plan']['registered'] = (isset($result->user_data->registered) && (int) $result->user_data->registered > 0 ? true : false);
                $accountPlan['plan']['bonus_available'] = (isset($result->user_data->bonus_available) && (int) $result->user_data->bonus_available > 0 ? true : false);
                $accountPlan['plan']['display_name'] = (isset($result->user_data->ass_user_email) && !empty($result->user_data->ass_user_email) ? sanitize_text_field(wp_unslash($result->user_data->ass_user_email)) : '');

                update_option('ASSI_PLUGIN_ACCOUNT', $accountPlan, false);
            } else {
                update_option('ASSI_PLUGIN_ACCOUNT', array(
                    'plan' => array(
                        'plan_id' => 1,
                        'credits_open' => 0,
                        'credits_total' => 0,
                        'max_chats' => 10,
                        'max_templates' => 10,
                        'registered' => false,
                        'addons' => array(
                            'normal' => array(
                                'credits_open' => 0,
                                'credits_total' => 0
                            ),
                            'promotion' => array(
                                'credits_open' => 0,
                                'credits_total' => 0
                            )
                        )
                    )
                        ), false);
                $accountPlan = get_option('ASSI_PLUGIN_ACCOUNT');
            }
        } else {
            $blogUserToken = $userExist->blog_user_token;
            if (empty($accountPlan)) {
                update_option('ASSI_PLUGIN_ACCOUNT', array(
                    'plan' => array(
                        'plan_id' => 0,
                        'credits_open' => 0,
                        'credits_total' => 0,
                        'max_chats' => 0,
                        'max_templates' => 0,
                        'registered' => false,
                        'addons' => array(
                            'normal' => array(
                                'credits_open' => 0,
                                'credits_total' => 0
                            ),
                            'promotion' => array(
                                'credits_open' => 0,
                                'credits_total' => 0
                            )
                        )
                    )
                ), false);
            }
        }
        define('ASSI_PLUGIN_BLOG_USER_TOKEN', $blogUserToken);
        $accountSettings = get_option('ASSI_PLUGIN_BLOG_USER_OPTION_' . $this->blogUserData->ID);
        if (!$accountSettings) {
            $accountSettings = array(
                'content_creator' => array(
                    'language' => $this->blogLanguage,
                    'tone' => '',
                    'point_of_view' => '',
                    'content_length' => ''
                ),
                'image_generator' => array(
                    'size' => '',
                    'quality' => '',
                    'output_format' => ''
                )
            );
            update_option('ASSI_PLUGIN_BLOG_USER_OPTION_' . $this->blogUserData->ID, $accountSettings, false);
        }

        define('ASSI_PLUGIN_BLOG_ACCESS_TOKEN', (get_option('ASSI_PLUGIN_BLOG_ACCESS_TOKEN') ? get_option('ASSI_PLUGIN_BLOG_ACCESS_TOKEN') : ''));
        define('ASSI_ACCOUNT_REGISTERED', (isset($accountPlan['plan']['registered']) ? (int) $accountPlan['plan']['registered'] : 0));
        define('ASSI_ACCOUNT_BONUS_AVAILABLE', (isset($accountPlan['plan']['bonus_available']) ? (int) $accountPlan['plan']['bonus_available'] : 0));
        define('ASSI_ACCOUNT_CREDITS_OPEN', (isset($accountPlan['plan']['credits_open']) ? (int) $accountPlan['plan']['credits_open'] : 0));
        define('ASSI_ACCOUNT_CREDITS_TOTAL', (isset($accountPlan['plan']['credits_total']) ? (int) $accountPlan['plan']['credits_total'] : 0));
        define('ASSI_ACCOUNT_PLAN_ID', (isset($accountPlan['plan']['plan_id']) ? (int) $accountPlan['plan']['plan_id'] : 0));
        define('ASSI_ACCOUNT_MAX_CHATS', (isset($accountPlan['plan']['max_chats']) && (int) $accountPlan['plan']['max_chats'] > 0 ? (int) $accountPlan['plan']['max_chats'] : 0));
        define('ASSI_ACCOUNT_MAX_TEMPLATES', (isset($accountPlan['plan']['max_templates']) && (int) $accountPlan['plan']['max_templates'] > 0 ? (int) $accountPlan['plan']['max_templates'] : 0));
        define('ASSI_ACCOUNT_PLAN_ADDONS', (isset($accountPlan['plan']['addons']) && !empty($accountPlan['plan']['addons']) ? $accountPlan['plan']['addons'] : array()));
    }

    public function createMenu() {
        $menu = array(
            array(
                'id' => 'dashboard',
                'display_name' => __('Dashboard', 'assistini'),
                'role' => 'assistini_access',
                'wp_sidebar' => true,
                'ass_sidebar' => 'overview',
                'ass_icon' => 'bi-grid'
            ),
            array(
                'id' => 'chat',
                'display_name' => __('Content Creator', 'assistini'),
                'role' => 'assistini_access',
                'wp_sidebar' => true,
                'ass_sidebar' => 'overview',
                'ass_icon' => 'bi-chat-dots'
            ),
            array(
                'id' => 'template',
                'display_name' => __('Templates', 'assistini'),
                'role' => 'assistini_access',
                'wp_sidebar' => true,
                'ass_sidebar' => 'overview',
                'ass_icon' => 'bi-file-earmark-text'
            ),
            array(
                'id' => 'settings',
                'display_name' => 'Settings',
                'role' => 'assistini_access',
                'wp_sidebar' => true,
                'ass_sidebar' => 'overview',
                'ass_icon' => 'bi-gear'
            ),
            array(
                'id' => 'notification',
                'display_name' => __('Notifications', 'assistini'),
                'role' => 'assistini_access',
                'wp_sidebar' => true,
                'ass_sidebar' => 'overview',
                'ass_icon' => 'bi-bell'
            ),
            array(
                'id' => 'account',
                'display_name' => __('Account', 'assistini'),
                'role' => 'assistini_access',
                'wp_sidebar' => true,
                'ass_sidebar' => 'account',
                'ass_icon' => 'bi-person'
            ),
            array(
                'id' => 'support',
                'display_name' => __('Support', 'assistini'),
                'role' => 'assistini_access',
                'wp_sidebar' => false,
                'ass_sidebar' => 'account',
                'ass_icon' => 'bi-chat'
            )
        );
        define('ASSI_PLUGIN_MENU_ITEMS', serialize($menu));

        global $submenu;
        $parent = 'assistini';
        add_menu_page('Assistini Title', 'Assistini', 'assistini_access', $parent, array($this, 'assiPageGeneral'), plugins_url('/assets/images/ass_nav_icon.png', ASSI_PLUGIN_FILE));

        foreach ($menu as $item) {
            if (isset($item['wp_sidebar']) && $item['wp_sidebar']) {
                $submenu[$parent][] = array($item['display_name'], $item['role'], 'admin.php?page=assistini#/' . $item['id']);
            }
        }
    }

    public function addRootAssets() {
        wp_enqueue_style('ASSIBOOTSTRAPCSS');
        wp_enqueue_style('ASSIBOOTSTRAPICONSCSS');
        wp_enqueue_style('ASSIROOTCSS');
        wp_enqueue_style('ASSICOLORSCSS');
        wp_enqueue_style('ASSIFONTPOPPINSCSS');
        wp_enqueue_style('ASSIFONTNUNITOCSS');
        wp_enqueue_script('ASSIBOOTSTRAPJS');
        wp_enqueue_script('ASSIMARKDOWNJS');
        wp_enqueue_script('ASSICIRCLEPROGRESSJS');
        wp_enqueue_script('ASSIROOTJS');
        $current_user = wp_get_current_user();
        $globalAlerts = get_option('ASSI_PLUGIN_GLOBAL_ALERTS');
        wp_localize_script('ASSIROOTJS', 'assi_plugin_data', array(
            'manage_options' => current_user_can('manage_options'),
            'allow_server_connection' => (defined('ASSI_PLUGIN_CONNECTION_TO_SERVER') && ASSI_PLUGIN_CONNECTION_TO_SERVER ? true : false),
            'plugin_path' => plugins_url('', ASSI_PLUGIN_FILE),
            'settings' => get_option('ASSI_PLUGIN_BLOG_USER_OPTION_' . ASSI_PLUGIN_BLOG_USER_ID),
            'user_credits' => array(
                'credits_open' => (defined('ASSI_ACCOUNT_CREDITS_OPEN') ? ASSI_ACCOUNT_CREDITS_OPEN : 0),
                'credits_total' => (defined('ASSI_ACCOUNT_CREDITS_TOTAL') ? ASSI_ACCOUNT_CREDITS_TOTAL : 0),
            ),
            'user_account' => get_option('ASSI_PLUGIN_ACCOUNT'),
            'blog_access_token' => get_option('ASSI_PLUGIN_BLOG_ACCESS_TOKEN'),
            'blog_user_token' => (defined('ASSI_PLUGIN_BLOG_USER_TOKEN') ? ASSI_PLUGIN_BLOG_USER_TOKEN : array()),
            'user_addons' => (defined('ASSI_ACCOUNT_PLAN_ADDONS') ? ASSI_ACCOUNT_PLAN_ADDONS : array()),
            'blog_user_first_name' => (isset($current_user->user_firstname) && !empty($current_user->user_firstname) ? $current_user->user_firstname : ''),
            'blog_user_last_name' => (isset($current_user->user_lastname) && !empty($current_user->user_lastname) ? $current_user->user_lastname : ''),
            'blog_user_display_name' => (isset($current_user->display_name) && !empty($current_user->display_name) ? $current_user->display_name : ''),
            'blog_user_email' => (isset($current_user->user_email) && !empty($current_user->user_email) ? $current_user->user_email : ''),
            'blog_language' => $this->blogLanguage,
            'custom_ai_connection' => get_option('ASSI_PLUGIN_CUSTOM_AI_CONNECTION'),
            'global_alerts' => (is_array($globalAlerts) ? $globalAlerts : array()),
        ));
    }

    public function assiPageGeneral() {
        $this->addRootAssets();
        require_once(ASSI_PLUGIN_DIR . 'views/ass/general.php');
    }

    public function createToolbarMenu() {
        if (!current_user_can('assistini_access')) {
            return;
        }
        global $wp_admin_bar;
        $seo_url = strtolower(get_admin_url(null, 'admin.php?page='));
        $title = '<div id="assistini-ab-icon" class="ab-item" style="padding-left: 25px; background-repeat: no-repeat; background-size: 16px auto; background-position: left center; background-image: url(\'' . esc_url(plugins_url('/assets/images/ass_nav_icon.png', ASSI_PLUGIN_FILE)) . '\');">' . esc_html__('Assistini', 'assistini') . '</div>';
        $wp_admin_bar->add_node(array(
            'id' => 'assistini',
            'title' => $title,
            'href' => $seo_url . 'assistini'
        ));
        if (defined('ASSI_PLUGIN_MENU_ITEMS') && !empty(ASSI_PLUGIN_MENU_ITEMS)) {
            $menuArray = unserialize(ASSI_PLUGIN_MENU_ITEMS);
            if (is_array($menuArray) && !empty($menuArray)) {
                foreach ($menuArray as $item) {
                    if (isset($item['wp_sidebar']) && $item['wp_sidebar'] == true) {
                        $wp_admin_bar->add_node(array(
                            'id' => $item['id'],
                            'title' => $item['display_name'],
                            'href' => $seo_url . 'assistini#/' . $item['id'],
                            'parent' => 'assistini'
                        ));
                    }
                }
            }
        }
    }

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

        global $wpdb;

        $createTables = function () use ($wpdb) {
            $tables = [
                "{$wpdb->prefix}assi_user" => [
                    'sql' => "CREATE TABLE `{$wpdb->prefix}assi_user` (
                        `id` int(11) NOT NULL AUTO_INCREMENT,
                        `blog_user_token` varchar(255) NOT NULL,
                        `blog_user_id` int(11) NOT NULL,
                        `register_date` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
                        PRIMARY KEY (`id`),
                        INDEX `blog_user_id` (`blog_user_id`),
                        INDEX `blog_user_token` (`blog_user_token`)
                    ) DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci AUTO_INCREMENT=1;",
                    'columns' => [
                        'id' => 'int(11) NOT NULL AUTO_INCREMENT',
                        'blog_user_token' => 'varchar(255) NOT NULL',
                        'blog_user_id' => 'int(11) NOT NULL',
                        'register_date' => 'DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP',
                    ]
                ],
                "{$wpdb->prefix}assi_user_notifications" => [
                    'sql' => "CREATE TABLE `{$wpdb->prefix}assi_user_notifications` (
                        `notification_id` INT NOT NULL,
                        `blog_user_id` INT NULL DEFAULT NULL,
                        `type` VARCHAR(50) NOT NULL,
                        `request_id` VARCHAR(100) NULL DEFAULT NULL,
                        `status` TINYINT NOT NULL DEFAULT '2',
                        `create_date` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
                        `notification_data` JSON NULL DEFAULT NULL,
                        UNIQUE (`notification_id`)
                    ) DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;",
                    'columns' => [
                        'notification_id' => 'INT NOT NULL',
                        'blog_user_id' => 'INT NULL DEFAULT NULL',
                        'type' => 'VARCHAR(50) NOT NULL',
                        'request_id' => 'VARCHAR(100) NULL DEFAULT NULL',
                        'status' => 'TINYINT NOT NULL DEFAULT \'2\'',
                        'create_date' => 'DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP',
                        'notification_data' => 'JSON NULL DEFAULT NULL',
                    ]
                ],
                "{$wpdb->prefix}assi_user_templates" => [
                    'sql' => "CREATE TABLE `{$wpdb->prefix}assi_user_templates` (
                        `id` int(11) NOT NULL AUTO_INCREMENT,
                        `blog_user_id` int(11) NULL DEFAULT NULL,
                        `create_date` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
                        `last_mod_date` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
                        `prompt_name` VARCHAR(50) NOT NULL,
                        `custom_prompt` JSON NULL DEFAULT NULL,
                        `blog_access` TINYINT NOT NULL DEFAULT '0',
                        PRIMARY KEY (`id`),
                        INDEX `blog_user_id` (`blog_user_id`)
                    ) DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;",
                    'columns' => [
                        'id' => 'int(11) NOT NULL AUTO_INCREMENT',
                        'blog_user_id' => 'int(11) NULL DEFAULT NULL',
                        'create_date' => 'DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP',
                        'last_mod_date' => 'DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP',
                        'prompt_name' => 'VARCHAR(50) NOT NULL',
                        'custom_prompt' => 'JSON NULL DEFAULT NULL',
                        'blog_access' => 'TINYINT NOT NULL DEFAULT \'0\'',
                    ]
                ],
                "{$wpdb->prefix}assi_user_history" => [
                    'sql' => "CREATE TABLE `{$wpdb->prefix}assi_user_history` (
                        `request_id` VARCHAR(50) NOT NULL,
                        `blog_user_id` int(11) NULL DEFAULT NULL,
                        `is_system` TINYINT NOT NULL DEFAULT '0',
                        `template_id` int(11) NOT NULL,
                        `type` VARCHAR(50) NOT NULL,
                        `category` VARCHAR(50) NOT NULL,
                        `create_date` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
                        `data` JSON NULL DEFAULT NULL,
                        UNIQUE (`request_id`),
                        INDEX `blog_user_id` (`blog_user_id`)
                    ) DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;",
                    'columns' => [
                        'request_id' => 'VARCHAR(50) NOT NULL',
                        'blog_user_id' => 'int(11) NULL DEFAULT NULL',
                        'is_system' => 'TINYINT NOT NULL DEFAULT \'0\'',
                        'template_id' => 'int(11) NOT NULL',
                        'type' => 'VARCHAR(50) NOT NULL',
                        'category' => 'VARCHAR(50) NOT NULL',
                        'create_date' => 'DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP',
                        'data' => 'JSON NULL DEFAULT NULL',
                    ]
                ],
            ];

            foreach ($tables as $table_name => $table_data) {
                maybe_create_table($table_name, $table_data['sql']);
                foreach ($table_data['columns'] as $column_name => $column_definition) {
                    $sql_add_column = "ALTER TABLE $table_name ADD $column_name $column_definition;";
                    maybe_add_column($table_name, $column_name, $sql_add_column);
                }
            }
        };

        if (is_multisite()) {
            $sites = get_sites(['fields' => 'ids']);
            foreach ($sites as $siteId) {
                switch_to_blog($siteId);
                $createTables();
                $this->initCaps();
                restore_current_blog();
            }
        } else {
            $createTables();
            $this->initCaps();
        }
    }

    public function initCaps() {
        $roles = wp_roles();
        foreach ($roles->roles as $roleName => $roleInfo) {
            $role = get_role($roleName);
            if ($role) {
                $role->add_cap('assistini_access');
            }
        }
    }

    public function deactivatePlugin() {
        remove_action('admin_init', array($this, 'registerAssets'));
        remove_action('admin_menu', array($this, 'createMenu'));
        remove_action('admin_bar_menu', array($this, 'createToolbarMenu'), 94);
        remove_action('init', array($this, 'defineCurrentUserId'));
        remove_action('admin_notices', array($this, 'initNotices'));
        remove_action('init', array($this, 'startHeartbeat'));
        deactivate_plugins(ASSI_PLUGIN_BASENAME);
    }

    public function initNotices() {
        if ($this->showConnectionNotice) {
            echo '<div class="notice notice-error ass-notice-connection is-dismissible"><p><i class="bi bi-x-lg text-danger me-1"></i>' . esc_html__('We we\'re unable to connect to the Assistini server!', 'assistini') . '</p></div>';
        }
        echo '<div class="notice notice-error ass-notice-heartbeat is-dismissible" style="display:none;"><p><i class="bi bi-x-lg text-danger me-1"></i>' . esc_html__('Live Notifications won\'t work due to the WordPress Heartbeat being disabled!', 'assistini') . '</p></div>';
        echo '<div class="notice notice-error ass-notice-nonce is-dismissible" style="display:none;"><p><i class="bi bi-x-lg text-danger me-1"></i>' . esc_html__('WordPress Session Timeout: For security reasons, WordPress automatically ends your current session if your website has been inactive for a while. Please reload this page to continue your work.', 'assistini') . '</p></div>';
        echo '<div class="notice ass-notice-editor-classic is-dismissible" style="display:none;"><p class="ass-notice-editor-classic-message"></p></div>';
    }

    public function initEditorSidebar() {
        wp_enqueue_media();
        wp_enqueue_style('ASSIEDITORSIDEBARCSS');
        wp_enqueue_style('ASSIBOOTSTRAPICONSCSS');
        wp_enqueue_style('ASSIFONTPOPPINSCSS');
        wp_enqueue_style('ASSIFONTNUNITOCSS');
        wp_enqueue_script('ASSICIRCLEPROGRESSJS');
        wp_enqueue_script('ASSIEDITORSIDEBARJS');
        wp_enqueue_script('ASSIMARKDOWNJS');
        wp_set_script_translations('ASSIEDITORSIDEBARJS', 'assistini', plugin_dir_path(__FILE__) . '/languages/');
        $globalAlerts = get_option('ASSI_PLUGIN_GLOBAL_ALERTS');
        wp_localize_script('ASSIEDITORSIDEBARJS', 'assi_plugin_data', array(
            'assi_security_nonce' => wp_create_nonce('assi_security_nonce'),
            'plugin_path' => plugins_url('', ASSI_PLUGIN_FILE),
            'plugin_token' => (defined('ASSI_PLUGIN_TOKEN') ? ASSI_PLUGIN_TOKEN : ''),
            'manage_options' => current_user_can('manage_options'),
            'allow_server_connection' => ((int) get_option('ASSI_PLUGIN_CONNECTION_TO_SERVER') == 1 ? 'true' : 'false'),
            'form_options' => array(
                'language' => ASSI_Tools::getAllLanguages(),
                'tone' => ASSI_Tools::getTonality(),
                'point_of_view' => ASSI_Tools::getPointOfView(),
                'size' => ASSI_Tools::getSize(),
                'quality' => ASSI_Tools::getQuality(),
                'output_format' => ASSI_Tools::getOutputFormat(),
                'art_style' => ASSI_Tools::getArtStyle(),
                'custom_styles' => get_option('ASSI_PLUGIN_CUSTOM_STYLES_' . ASSI_PLUGIN_BLOG_USER_ID),
            ),
            'translations' => array(
                'models' => ASSI_Tools::getModelTranslations()
            ),
            'user_data' => array(
                'plan_id' => (defined('ASSI_ACCOUNT_PLAN_ID') ? (int) ASSI_ACCOUNT_PLAN_ID : 0),
                'credits_open' => (defined('ASSI_ACCOUNT_CREDITS_OPEN') ? (int) ASSI_ACCOUNT_CREDITS_OPEN : 0),
                'credits_total' => (defined('ASSI_ACCOUNT_CREDITS_TOTAL') ? (int) ASSI_ACCOUNT_CREDITS_TOTAL : 0),
                'addons' => (defined('ASSI_ACCOUNT_PLAN_ADDONS') ? ASSI_ACCOUNT_PLAN_ADDONS : array())
            ),
            'settings' => get_option('ASSI_PLUGIN_BLOG_USER_OPTION_' . ASSI_PLUGIN_BLOG_USER_ID),
            'editor_type' => 'default',
            'custom_ai_connection' => get_option('ASSI_PLUGIN_CUSTOM_AI_CONNECTION'),
            'global_alerts' => (is_array($globalAlerts) ? $globalAlerts : array()),
            'user_datetime' => array(
                'timezone' => wp_timezone_string(),
                'date_format' => get_option('date_format'),
                'time_format' => get_option('time_format')
            )
        ));
    }

    public function initClassicEditorSidebar($hook) {

        if (!use_block_editor_for_post_type('post') && in_array($hook, array('post.php', 'post-new.php'))) {

            wp_enqueue_style('ASSIEDITORSIDEBARCSS');
            wp_enqueue_style('ASSIBOOTSTRAPICONSCSS');
            wp_enqueue_style('ASSIFONTPOPPINSCSS');
            wp_enqueue_style('ASSIFONTNUNITOCSS');
            wp_enqueue_script('ASSICIRCLEPROGRESSJS');
            wp_enqueue_script('ASSIEDITORSIDEBARJS');
            wp_enqueue_script('ASSIMARKDOWNJS');
            $globalAlerts = get_option('ASSI_PLUGIN_GLOBAL_ALERTS');
            wp_localize_script('ASSIEDITORSIDEBARJS', 'assi_plugin_data', array(
                'assi_security_nonce' => wp_create_nonce('assi_security_nonce'),
                'plugin_path' => plugins_url('', ASSI_PLUGIN_FILE),
                'plugin_token' => (defined('ASSI_PLUGIN_TOKEN') ? ASSI_PLUGIN_TOKEN : ''),
                'manage_options' => current_user_can('manage_options'),
                'allow_server_connection' => ((int) get_option('ASSI_PLUGIN_CONNECTION_TO_SERVER') == 1 ? 'true' : 'false'),
                'form_options' => array(
                    'language' => ASSI_Tools::getAllLanguages(),
                    'tone' => ASSI_Tools::getTonality(),
                    'point_of_view' => ASSI_Tools::getPointOfView(),
                    'size' => ASSI_Tools::getSize(),
                    'quality' => ASSI_Tools::getQuality(),
                    'output_format' => ASSI_Tools::getOutputFormat(),
                    'art_style' => ASSI_Tools::getArtStyle(),
                    'custom_styles' => get_option('ASSI_PLUGIN_CUSTOM_STYLES_' . ASSI_PLUGIN_BLOG_USER_ID),
                ),
                'translations' => array(
                    'models' => ASSI_Tools::getModelTranslations()
                ),
                'user_data' => array(
                    'plan_id' => (defined('ASSI_ACCOUNT_PLAN_ID') ? (int) ASSI_ACCOUNT_PLAN_ID : 0),
                    'credits_open' => (defined('ASSI_ACCOUNT_CREDITS_OPEN') ? (int) ASSI_ACCOUNT_CREDITS_OPEN : 0),
                    'credits_total' => (defined('ASSI_ACCOUNT_CREDITS_TOTAL') ? (int) ASSI_ACCOUNT_CREDITS_TOTAL : 0),
                    'addons' => (defined('ASSI_ACCOUNT_PLAN_ADDONS') ? ASSI_ACCOUNT_PLAN_ADDONS : array())
                ),
                'settings' => get_option('ASSI_PLUGIN_BLOG_USER_OPTION_' . ASSI_PLUGIN_BLOG_USER_ID),
                'editor_type' => 'classic',
                'shortcodes' => array(array('text' => 'Slider', 'shortcode' => '[slider]'), array('text' => 'Video', 'shortcode' => '[video]')),
                'custom_ai_connection' => get_option('ASSI_PLUGIN_CUSTOM_AI_CONNECTION'),
                'global_alerts' => (is_array($globalAlerts) ? $globalAlerts : array())
            ));
        }
    }

    public function mein_custom_tinymce_plugin($plugin_array) {
        $plugin_array['mein_custom_button'] = plugins_url('assets/js/editor/tinymce.js', ASSI_PLUGIN_FILE);
        return $plugin_array;
    }

    public function mein_custom_tinymce_button($buttons) {
        array_push($buttons, 'mein_custom_button');
        return $buttons;
    }

    public function checkForUpdate() {
        $lastVersion = get_option('ASSI_PLUGIN_VERSION');
        if (!$lastVersion || (int) $lastVersion < (int) ASSI_PLUGIN_VERSION) {
            update_option('ASSI_PLUGIN_VERSION', (int) ASSI_PLUGIN_VERSION, false);
            $this->activatePlugin();
        }
    }
}
