<?php
/**
 * ST_ProQyz setup
 *
 * @package ST_ProQyz
 * @since   1.0.0
 */

defined( 'ABSPATH' ) || exit;

/**
 *
 * @class ST_ProQyz
 */
class ST_ProQyz {

	/**
	 * Ielts_Lms version.
	 *
	 * @var string
	 */
	public $version = ST_VERSION;
	private $api_endpoint_slug = "proqyz";
    protected static $_instance = null;

    /**
	 * Main Ielts_Lms Instance.
	 *
	 * Ensures only one instance of Ielts_Lms is loaded or can be loaded.
	 *
	 * @since 1.0
	 * @static
	 * @see ST()
	 * @return Ielts_Lms - Main instance.
	 */
	public static function instance() {
		if ( is_null( self::$_instance ) ) {
			self::$_instance = new self();
		}
		return self::$_instance;
	}

    /**
	 * Ielts_Lms Constructor.
	 */
	public function __construct() {
		$this->define_constants(); // done
		$this->define_globals();
		$this->version_fix();
		$this->define_tables(); // done
		$this->default_options();
		$this->includes(); // done
		//$this->init_hooks(); // pending
	}

	/**
	 * ProQyz debug log – write to proqyz/logs (gated by st_proqyz_custom_debug_log option).
	 * Usable globally via ST_ProQyz()->log() from any class inside ProQyz.
	 *
	 * @param string $type    Log type (e.g. INFO, DEBUG, ERROR, HOOK).
	 * @param mixed  $message Message or variable (arrays/objects logged as print_r).
	 * @return bool True if written, false otherwise.
	 */
	public function log( $type, $message ) {
		return class_exists( 'ST_ProQyz_Debug_Log', false ) ? ST_ProQyz_Debug_Log::log( $type, $message ) : false;
	}

	/**
	 * Debug log shorthand: INFO.
	 *
	 * @param mixed $message Message or variable to log.
	 * @return bool
	 */
	public function log_info( $message ) {
		return $this->log( 'INFO', $message );
	}

	/**
	 * Debug log shorthand: DEBUG.
	 *
	 * @param mixed $message Message or variable to log.
	 * @return bool
	 */
	public function log_debug( $message ) {
		return $this->log( 'DEBUG', $message );
	}

	/**
	 * Debug log shorthand: ERROR.
	 *
	 * @param mixed $message Message or variable to log.
	 * @return bool
	 */
	public function log_error( $message ) {
		return $this->log( 'ERROR', $message );
	}

	/**
	 * Debug log shorthand: HOOK (for custom hooks).
	 *
	 * @param mixed $message Message or variable to log.
	 * @return bool
	 */
	public function log_hook( $message ) {
		return $this->log( 'HOOK', $message );
	}

    /**
	 * Define ST Constants.
	 */
	private function define_constants() {
		// $upload_dir = wp_upload_dir( null, false );
		$this->define( 'ST_PROQYZ_ABSPATH', dirname( ST_PROQYZ_PLUGIN_FILE ) . '/' );
		$this->define( 'ST_PROQYZ_PLUGIN_BASENAME', plugin_basename(ST_PROQYZ_PLUGIN_FILE ) );
		$this->define( 'ST_PROQYZ_VERSION', $this->version );
		$this->define( 'ST_PROQYZ_ENDPOINT', ST_MAIN_ENDPOINT . "/" .$this->api_endpoint_slug );
		$this->define( 'ST_PROQYZ_SLUG', ST_SLUG."-proqyz");
		$this->define( 'ST_PROQYZ_LIBS_DIR', ST_PROQYZ_ABSPATH . "includes/libs");
		$this->define( 'ST_PROQYZ_PUBLIC_URL', plugin_dir_url(ST_PROQYZ_PLUGIN_FILE) . "includes/public");
		$this->define( 'ST_PROQYZ_TEMPLATE_DIR', ST_PROQYZ_ABSPATH . "includes/templates");
		$this->define( 'ST_PROQYZ_PLUGIN_URL', plugin_dir_url(ST_PROQYZ_PLUGIN_FILE) );

	}

	private function define_globals() {
		global $wpdb, 
			$table_proqyz_v3_progress_submissions, // main core submission entry table 
			$table_proqyz_v3_progress_submissions_meta,  // core submission meta table
			$table_proqyz_v3_progress_meta_submissions, // speaking submission meta table 
			$table_proqyz_v3_submissions_review, // review table
			$table_proqyz_v3_submissions_review_meta, // review meta table
			$table_proqyz_v3_submissions_versioning, // versioning table (quizzes)
			// v3 dedicated tables for json, session_detail, and score
			$table_proqyz_v3_progress_submissions_user_response, // user response table - json
			$table_proqyz_v3_progress_submissions_session, // session detail table - session_detail
			$table_proqyz_v3_progress_submissions_score, // score table - score
			// v3 submissions evaluation metadata table (usermeta-like for sessions)
			$table_proqyz_v3_submissions_evaluation_meta, // evaluation metadata table
			$table_proqyz_fullmock_tests_progress; // fullmock test sessions table (old)


		global 
			$ST_OPTION_st_proqyz__license_key, 
			$ST_OPTION_st_proqyz__enable_key,
			$ST_OPTION_st_proqyz__auth_redirect_enable_key,
			$ST_OPTION_st_proqyz__auth_signup_url_key,
			$ST_OPTION_st_proqyz__auth_signin_url_key,
			$ST_OPTION_st_proqyz__auth_ielts_account_complete,
			$ST_OPTION_st_proqyz__IELTS_LMS,
			$ST_OPTION_st_proqyz__GOV_LMS,
			$ST_OPTION_st_proqyz__PDF_QUIZ_LMS,
			$ST_OPTION_st_proqyz__leaderboard, 
			$ST_OPTION_st_proqyz__result_message,
			$ST_OPTION_st_proqyz__result_message_gov_competitive_exam,
			$ST_OPTION_st_proqyz__result_message_pdf_quiz,
			$ST_OPTION_st_proqyz__result_message_ielts_reading_quiz,
			$ST_OPTION_st_proqyz__result_message_ielts_listening_quiz,
			$ST_OPTION_st_proqyz__result_message_ielts_writing_quiz,
			$ST_OPTION_st_proqyz__result_message_ielts_speaking_quiz;

		global 
			$ST_OPTION_st_proqyz_IELTS_LMS_enable_evaluation,
			$ST_OPTION_st_proqyz_IELTS_LMS_writing_task1_evaluation_enable,
			$ST_OPTION_st_proqyz_IELTS_LMS_writing_task2_evaluation_enable,
			$ST_OPTION_st_proqyz_IELTS_LMS_writing_task1and2_evaluation_enable,
			$ST_OPTION_st_proqyz_IELTS_LMS_writing_task1_evaluation_plan_id,
			$ST_OPTION_st_proqyz_IELTS_LMS_writing_task2_evaluation_plan_id,
			$ST_OPTION_st_proqyz_IELTS_LMS_writing_task1and2_evaluation_plan_id,
			$ST_OPTION_st_proqyz_IELTS_LMS_writing_evaluation_instructions,
			$ST_OPTION_st_proqyz_IELTS_LMS_speaking_evaluation_instructions,
			$ST_OPTION_st_proqyz_IELTS_LMS_speaking_evaluation_enable,
			$ST_OPTION_st_proqyz_IELTS_LMS_speaking_evaluation_plan_id;

		global
			$ST_OPTION_st_proqyz_IELTS_LMS_enable_ai_evaluation,
			$ST_OPTION_st_proqyz_IELTS_LMS_ai_writing_task1_evaluation_enable,
			$ST_OPTION_st_proqyz_IELTS_LMS_ai_writing_task2_evaluation_enable,
			$ST_OPTION_st_proqyz_IELTS_LMS_ai_writing_task1and2_evaluation_enable,
			$ST_OPTION_st_proqyz_IELTS_LMS_ai_writing_task1_evaluation_plan_id,
			$ST_OPTION_st_proqyz_IELTS_LMS_ai_writing_task2_evaluation_plan_id,
			$ST_OPTION_st_proqyz_IELTS_LMS_ai_writing_task1and2_evaluation_plan_id,
			$ST_OPTION_st_proqyz_IELTS_LMS_ai_writing_evaluation_instructions,
			$ST_OPTION_st_proqyz_IELTS_LMS_ai_speaking_evaluation_enable,
			$ST_OPTION_st_proqyz_IELTS_LMS_ai_speaking_evaluation_plan_id,
			$ST_OPTION_st_proqyz_IELTS_LMS_ai_speaking_evaluation_instructions;

		/**
		 * v2.1.0.1 
		 * type: cart, wallet keys
		 */
		global 
			$st_proqyz__evaluation_cart__writing_task_1,
			$st_proqyz__evaluation_cart__writing_task_2,
			$st_proqyz__evaluation_cart__writing_task_1_ai,
			$st_proqyz__evaluation_cart__writing_task_2_ai,
			$st_proqyz__evaluation_cart__speaking_tasks,
			$st_proqyz__evaluation_cart__speaking_tasks_ai;


		
		
		global 
			$ST_OPTION_checkout_page;

		/**
		 * since 2.0.0 -beta
		 */	
		global
			$ST_EMAILS;
		/**
		 * since 2.0.3.1
		 */
		global 
			$ST_OPTION_st_proqyz__open_ai_endpoint,
			$ST_OPTION_st_proqyz__open_ai_modal,
			$ST_OPTION_st_proqyz__open_ai_enable,
			$ST_OPTION_st_proqyz__open_ai_apikey;

		/**
		 * since 2.1.0 - Database version tracking
		 */
		global
			$ST_OPTION_st_proqyz__db_version,
			$ST_OPTION_st_proqyz__migration_status;

        // v3 tables for migration with quiz/course versioning
		$table_proqyz_v3_progress_submissions						= $wpdb->prefix.'st_proqyz_v3_progress_submissions';
		$table_proqyz_v3_progress_submissions_meta					= $wpdb->prefix.'st_proqyz_v3_progress_submissions_meta';
		$table_proqyz_v3_progress_meta_submissions					= $wpdb->prefix.'st_proqyz_v3_progress_meta_submissions';
		$table_proqyz_v3_submissions_review							= $wpdb->prefix.'st_proqyz_v3_submissions_review';
		$table_proqyz_v3_submissions_review_meta					= $wpdb->prefix.'st_proqyz_v3_submissions_review_meta';
		$table_proqyz_v3_submissions_versioning						= $wpdb->prefix.'st_proqyz_v3_submissions_versioning';
		// v3 dedicated tables for json, session_detail, and score (further size reduction)
		$table_proqyz_v3_progress_submissions_user_response			= $wpdb->prefix.'st_proqyz_v3_progress_submissions_user_response';
		$table_proqyz_v3_progress_submissions_session				= $wpdb->prefix.'st_proqyz_v3_progress_submissions_session';
		$table_proqyz_v3_progress_submissions_score					= $wpdb->prefix.'st_proqyz_v3_progress_submissions_score';
		// v3 submissions evaluation metadata table (usermeta-like for sessions)
		$table_proqyz_v3_submissions_evaluation_meta				= $wpdb->prefix.'st_proqyz_v3_submissions_evaluation_meta';
	    $table_proqyz_fullmock_tests_progress						= $wpdb->prefix.'st_proqyz_fullmock_tests_progress';




		$ST_OPTION_st_proqyz__license_key 							= 'st_proqyz__license-key';
		$ST_OPTION_st_proqyz__enable_key      						= 'st_proqyz__enable';

		$ST_OPTION_st_proqyz__auth_redirect_enable_key      		= 'st_proqyz__auth-redirect-enable';
		$ST_OPTION_st_proqyz__auth_signup_url_key          			= 'st_proqyz__auth-signup-url';
		$ST_OPTION_st_proqyz__auth_signin_url_key          			= 'st_proqyz__auth-signin-url';
		$ST_OPTION_st_proqyz__auth_ielts_account_complete   		= 'st_proqyz__auth-ielts-account-complete';

		$ST_OPTION_st_proqyz__IELTS_LMS								= 'st_proqyz__IELTS-LMS';
		$ST_OPTION_st_proqyz__GOV_LMS								= 'st_proqyz__GOV-LMS';
		$ST_OPTION_st_proqyz__PDF_QUIZ_LMS							= 'st_proqyz__pdf-quiz-lms';

		$ST_OPTION_st_proqyz__leaderboard							= "st_proqyz__leaderboard";
		$ST_OPTION_st_proqyz__result_message						= "st_proqyz__custom-result";
		$ST_OPTION_st_proqyz__result_message_gov_competitive_exam 	= 'st_proqyz__custom-result--gov-competitive_exam';
		$ST_OPTION_st_proqyz__result_message_pdf_quiz				= 'st_proqyz__custom-result--proqyz-pdf-quiz';
		$ST_OPTION_st_proqyz__result_message_ielts_reading_quiz		= 'st_proqyz__custom-result--ielts-reading';
		$ST_OPTION_st_proqyz__result_message_ielts_listening_quiz	= 'st_proqyz__custom-result--ielts-listening';
		$ST_OPTION_st_proqyz__result_message_ielts_writing_quiz		= 'st_proqyz__custom-result--ielts-writing';
		$ST_OPTION_st_proqyz__result_message_ielts_speaking_quiz	= 'st_proqyz__custom-result--ielts-speaking';

		/**
		 * since 1.2.1  - 
		 * ielts writing speaking evalution
		 * 
		 */
		$ST_OPTION_st_proqyz_IELTS_LMS_writing_task1_evaluation_enable 			= 'st_proqyz__IELTS-LMS-WRITING-TASK-1-EVALUATION-ENABLE';
		$ST_OPTION_st_proqyz_IELTS_LMS_writing_task2_evaluation_enable 			= 'st_proqyz__IELTS-LMS-WRITING-TASK-2-EVALUATION-ENABLE';
		$ST_OPTION_st_proqyz_IELTS_LMS_writing_task1and2_evaluation_enable 		= 'st_proqyz__IELTS-LMS-WRITING-TASK-1-AND-2-EVALUATION-ENABLE';
		
		$ST_OPTION_st_proqyz_IELTS_LMS_writing_task1_evaluation_plan_id 		= 'st_proqyz__IELTS-LMS-WRITING-TASK-1-EVALUATION-PLAN-ID';
		$ST_OPTION_st_proqyz_IELTS_LMS_writing_task2_evaluation_plan_id 		= 'st_proqyz__IELTS-LMS-WRITING-TASK-2-EVALUATION-PLAN-ID';
		$ST_OPTION_st_proqyz_IELTS_LMS_writing_task1and2_evaluation_plan_id 	= 'st_proqyz__IELTS-LMS-WRITING-TASK-1-AND-2-EVALUATION-PLAN-ID';
		$ST_OPTION_st_proqyz_IELTS_LMS_enable_evaluation						= 'st_proqyz__IELTS-LMS-ENABLE-EVALUATION';

		$ST_OPTION_st_proqyz_IELTS_LMS_writing_evaluation_instructions 			= 'st_proqyz__IELTS-LMS-WRITING-EVALUATION-INSTRUCTIONS';
		$ST_OPTION_st_proqyz_IELTS_LMS_speaking_evaluation_instructions 		= 'st_proqyz__IELTS-LMS-SPEAKING-EVALUATION-INSTRUCTIONS';

		$ST_OPTION_st_proqyz_IELTS_LMS_speaking_evaluation_enable 				= 'st_proqyz__IELTS-LMS-SPEAKING-EVALUATION-ENABLE';
		$ST_OPTION_st_proqyz_IELTS_LMS_speaking_evaluation_plan_id 				= 'st_proqyz__IELTS-LMS-SPEAKING-EVALUATION-PLAN-ID';


		$ST_OPTION_st_proqyz_IELTS_LMS_enable_ai_evaluation						= 'st_proqyz__IELTS-LMS-AI-EVALUATION-ENABLE';
		$ST_OPTION_st_proqyz_IELTS_LMS_ai_writing_task1_evaluation_enable		= 'st_proqyz__IELTS-LMS-AI-WRITING-TASK-1-EVALUATION-ENABLE';
		$ST_OPTION_st_proqyz_IELTS_LMS_ai_writing_task2_evaluation_enable		= 'st_proqyz__IELTS-LMS-AI-WRITING-TASK-2-EVALUATION-ENABLE';
		$ST_OPTION_st_proqyz_IELTS_LMS_ai_writing_task1and2_evaluation_enable	= 'st_proqyz__IELTS-LMS-AI-WRITING-TASK-1-AND-2-EVALUATION-ENABLE';
		$ST_OPTION_st_proqyz_IELTS_LMS_ai_writing_task1_evaluation_plan_id 		= 'st_proqyz__IELTS-LMS-AI-WRITING-TASK-1-EVALUATION-PLAN-ID';
		$ST_OPTION_st_proqyz_IELTS_LMS_ai_writing_task2_evaluation_plan_id		= 'st_proqyz__IELTS-LMS-AI-WRITING-TASK-2-EVALUATION-PLAN-ID';
		$ST_OPTION_st_proqyz_IELTS_LMS_ai_writing_task1and2_evaluation_plan_id	= 'st_proqyz__IELTS-LMS-AI-WRITING-TASK-1-AND-2-EVALUATION-PLAN-ID';
		$ST_OPTION_st_proqyz_IELTS_LMS_ai_writing_evaluation_instructions		= 'st_proqyz__IELTS-LMS-AI-WRITING-EVALUATION-INSTRUCTIONS';	

		$ST_OPTION_st_proqyz_IELTS_LMS_ai_speaking_evaluation_enable			= 'st_proqyz__IELTS-LMS-AI-SPEAKING-EVALUATION-ENABLE';
		$ST_OPTION_st_proqyz_IELTS_LMS_ai_speaking_evaluation_plan_id		= 'st_proqyz__IELTS-LMS-AI-SPEAKING-EVALUATION-PLAN-ID';
		$ST_OPTION_st_proqyz_IELTS_LMS_ai_speaking_evaluation_instructions	= 'st_proqyz__IELTS-LMS-AI-SPEAKING-EVALUATION-INSTRUCTIONS';

		/**
		 * v2.1.0.1 
		 * type: cart, wallet keys
		 */
		$st_proqyz__evaluation_cart__writing_task_1								= 'st_proqyz__evaluation-cart__writing-task-1';
		$st_proqyz__evaluation_cart__writing_task_2								= 'st_proqyz__evaluation-cart__writing-task-2';
		$st_proqyz__evaluation_cart__writing_task_1_ai							= 'st_proqyz__evaluation-cart__writing-task-1-ai';
		$st_proqyz__evaluation_cart__writing_task_2_ai							= 'st_proqyz__evaluation-cart__writing-task-2-ai';
		$st_proqyz__evaluation_cart__speaking_tasks								= 'st_proqyz__evaluation-cart__speaking-tasks';
		$st_proqyz__evaluation_cart__speaking_tasks_ai							= 'st_proqyz__evaluation-cart__speaking-tasks-ai';


		/**
		 * since 1.2.2 - fix
		 */
		$ST_OPTION_checkout_page = 'st_checkout-page';

		/**
		 * since 2.0.0
		 */
		$ST_CUSTOM_EMAIL_TEMPLATES = [];

		ob_start(); ?>
			<p class="p1">Dear {teacher_username},</p>
            <p class="p1">{student_username} has successfully completed the {quiz_title}.</p>
            <p>Result: {result_url}</p>
            Thanks,
		<?php $ST_CUSTOM_EMAIL_TEMPLATES['on-test-submit-teacher'] = ob_get_clean();

		ob_start(); ?>
			<p class="p1">Dear {admin_username},</p>
            <p class="p1">{student_username} has successfully completed the {quiz_title}.</p>
            Result: {result_url}
            
            Thanks,
		<?php $ST_CUSTOM_EMAIL_TEMPLATES['on-test-submit-owner'] = ob_get_clean();

        ob_start(); ?>
            <p class="p1">Dear {student_username},</p>
            <p class="p1">Congratulations on completing the {quiz_title}!</p>
            Result: {result_url}
            <p class="p1">Best wishes!</p>
        <?php $ST_CUSTOM_EMAIL_TEMPLATES['on-test-submit-student'] = ob_get_clean();


		ob_start(); ?>
			<p class="p1">Hi {student_username},</p>
            <p class="p1">Your writing test has been evaluated. You can now view your results and feedback by logging into your account.</p>
            <p class="p1"><strong>Test Name:</strong> {quiz_title}</p>
            <p class="p1"><strong>URL to Check Evaluation:</strong> {result_url}</p>
            <p class="p1">Here are the key points of your evaluation:
                <ul>
					<li><strong>Score:</strong> {overall_score}</li>
                </ul>
                Please take some time to review the feedback carefully. If you have any questions or need further clarification, feel free to reach out to me.
            </p>
            <p class="p1">Keep up the great work!</p>
            Best regards,
		<?php $ST_CUSTOM_EMAIL_TEMPLATES['on-writing-evaluation-student'] = ob_get_clean();

        ob_start(); ?>
            <p class="p1">Hi {admin_username},</p>
            <p class="p1">This is to inform you that {teacher_username} has evaluated the writing test for {student_username}. The results and feedback have been uploaded to the system.</p>
            <p class="p1"><strong>Test Name:</strong> {quiz_title}</p>
            <p class="p1"><strong>URL to Check Evaluation:</strong> {result_url}</p>
            <p class="p1">Please review the updates at your earliest convenience.</p>
            Thank you!
        <?php $ST_CUSTOM_EMAIL_TEMPLATES['on-writing-evaluation-owner'] = ob_get_clean();

        ob_start(); ?>
            <p class="p1">Hi {student_username},</p>
            <p class="p1">Your speaking test has been evaluated. You can now view your results and feedback by logging into your account.</p>
            <p class="p1"><strong>Test Name:</strong> {quiz_title}</p>
            <p class="p1"><strong>URL to Check Evaluation:</strong> {result_url}</p>
            <p class="p1">
                Here are the key points of your evaluation:
                <ul>
                    <li><strong>Score:</strong> {overall_score}</li>
                </ul>
                Please take some time to review the feedback carefully. If you have any questions or need further clarification, feel free to reach out to me.
            </p>
            <p class="p1">Keep up the great work!</p>
            Best regards,
        <?php $ST_CUSTOM_EMAIL_TEMPLATES['on-speaking-evaluation-student'] = ob_get_clean();

        ob_start(); ?>
            <p class="p1">Hi {admin_username},</p>
            <p class="p1">
                This is to inform you that {teacher_username} has evaluated the speaking test for {student_username}. The results and feedback have been uploaded to the system.
            </p>
            <p class="p1"><strong>Test Name:</strong> {quiz_title}</p>
            <p class="p1"><strong>URL to Check Evaluation:</strong> {result_url}</p>
            <p class="p1">Please review the updates at your earliest convenience.</p>
            Thank you!
        <?php $ST_CUSTOM_EMAIL_TEMPLATES['on-speaking-evaluation-owner'] = ob_get_clean();

		$ST_EMAILS = [
			# on test finish or submit [teacher]
			(object) [
                "ID"                    => null,
                "post_title"            => "Test submit (Teacher)",
                "post_name"             => "on-test-submit-teacher",
                "post_content"          => "Notifies all associated teachers by email when a student submits a test.",
                "trigger"               => "proqyz_email__on_test_submit_teacher",
                "post_meta"             => (array) [
                    "_proqyz__email-notification-enabled"   => 0,
                    "_proqyz__email-recipient"              => [],
                    "_proqyz__email-subject"                => "{student_username} Completed {quiz_title}",
                    "_proqyz__email-content"                => $ST_CUSTOM_EMAIL_TEMPLATES['on-test-submit-teacher'],
                    "_proqyz__email-roles"                  => ["teacher"]
                ]
            ],
			# on test finish or submit [owner]
			(object) [
                "ID"                    => null,
                "post_title"            => "Test submit (Administrator)",
                "post_name"             => "on-test-submit-owner",
                "post_content"          => "Notifies the site owner by email when a student submits a test.",
                "trigger"               => "proqyz_email__on_test_submit_owner",
                "post_meta"             => (array) [
                    "_proqyz__email-notification-enabled"   => 0,
                    "_proqyz__email-recipient"              => [],
                    "_proqyz__email-subject"                => "{student_username} Completed {quiz_title}",
                    "_proqyz__email-content"                => $ST_CUSTOM_EMAIL_TEMPLATES['on-test-submit-owner'],
                    "_proqyz__email-roles"                  => ["administrator"]
                ]
            ],
			# on test finish or submit [student]
			(object) [
                "ID"                    => null,
                "post_title"            => "Test submit (Student)",
                "post_name"             => "on-test-submit-student",
                "post_content"          => "Notifies students by email when they submit a test.",
                "trigger"               => "proqyz_email__on_test_submit_student",
                "post_meta"             => (array) [
                    "_proqyz__email-notification-enabled"   => 0,
                    "_proqyz__email-recipient"              => [],
                    "_proqyz__email-subject"                => "Your Quiz Results for {quiz_title}",
                    "_proqyz__email-content"                => $ST_CUSTOM_EMAIL_TEMPLATES['on-test-submit-student'],
                    "_proqyz__email-roles"                  => ["student", "subscriber"]
                ]
            ],
            
            # for writing
            (object) [
                "ID"                    => null,
                "post_title"            => "Writing Evaluation (Administrator)",
                "post_name"             => "on-writing-evaluation-owner",
                "post_content"          => "Notifies the site owner by email when a teacher evaluates a student's writing test.",
                "trigger"               => "proqyz_email__on_writing_evaluation_owner",
                "post_meta"             => (array) [
                    "_proqyz__email-notification-enabled"   => 0,
                    "_proqyz__email-recipient"              => [],
                    "_proqyz__email-subject"                => "Writing Test Evaluation Completed for {student_username}",
                    "_proqyz__email-content"                => $ST_CUSTOM_EMAIL_TEMPLATES['on-writing-evaluation-owner'],
                    "_proqyz__email-roles"                  => ["administrator"]
                ]
            ],
            (object) [
                "ID"                    => null,
                "post_title"            => "Writing Evaluation (Student)",
                "post_name"             => "on-writing-evaluation-student",
                "post_content"          => "Notifies students by email when their writing test is evaluated.",
                "trigger"               => "proqyz_email__on_writing_evaluation_student",
                "post_meta"             => (array) [
                    "_proqyz__email-notification-enabled"   => 0,
                    "_proqyz__email-recipient"              => [],
                    "_proqyz__email-subject"                => "Your Writing Test Results Are Now Available! ",
                    "_proqyz__email-content"                => $ST_CUSTOM_EMAIL_TEMPLATES['on-writing-evaluation-student'],
                    "_proqyz__email-roles"                  => ["student", "subscriber"]
                ]
            ], 
            /*
            (object) [
                "ID"                    => null,
                "post_title"            => "Writing Evaluation (Teacher)",
                "post_name"             => "on-writing-evaluation-teacher",
                "post_content"          => "When teacher evaluates student(s) writing results, a notification email will be sent to the teacher itself, or student(s) associated group teachers",
                "trigger"               => "proqyz_email__on_writing_evaluation_teacher",
                "post_meta"             => (array) [
                    "_proqyz__email-notification-enabled"   => 0,
                    "_proqyz__email-recipient"              => [],
                    "_proqyz__email-subject"                => "",
                    "_proqyz__email-content"                => "",
                    "_proqyz__email-roles"                  => ["teacher"]
                ]
            ], 
            */
            # for speaking
            (object) [
                "ID"                    => null,
                "post_title"            => "Speaking Evaluation (Administrator)",
                "post_name"             => "on-speaking-evaluation-owner",
                "post_content"          => "Notifies the site owner by email when a teacher evaluates a student's speaking test.",
                "trigger"               => "proqyz_email__on_speaking_evaluation_owner",
                "post_meta"             => (array) [
                    "_proqyz__email-notification-enabled"   => 0,
                    "_proqyz__email-recipient"              => [],
                    "_proqyz__email-subject"                => "Speking Test Evaluation Completed for {student_username}",
                    "_proqyz__email-content"                => $ST_CUSTOM_EMAIL_TEMPLATES['on-speaking-evaluation-owner'],
                    "_proqyz__email-roles"                  => ["administrator"]
                ]
            ],
            (object) [
                "ID"                    => null,
                "post_title"            => "Speaking Evaluation (Student)",
                "post_name"             => "on-speaking-evaluation-student",
                "post_content"          => "Notifies students by email when their speaking test is evaluated.",
                "trigger"               => "proqyz_email__on_speaking_evaluation_student",
                "post_meta"             => (array) [
                    "_proqyz__email-notification-enabled"   => 0,
                    "_proqyz__email-recipient"              => [],
                    "_proqyz__email-subject"                => "Your Speaking Test Results Are Now Available!",
                    "_proqyz__email-content"                => $ST_CUSTOM_EMAIL_TEMPLATES['on-speaking-evaluation-student'],
                    "_proqyz__email-roles"                  => ["student", "subscriber"]
                ]
            ],
            /*(object) [
                "ID"                    => null,
                "post_title"            => "Speaking Evaluation (Teacher)",
                "post_name"             => "on-speaking-evaluation-teacher",
                "post_content"          => "When teacher evaluates student(s) speaking results, a notification email will be sent to the teacher itself, or student(s) associated group teachers",
                "trigger"               => "proqyz_email__on_speaking_evaluation_teacher",
                "post_meta"             => (array) [
                    "_proqyz__email-notification-enabled"   => 0,
                    "_proqyz__email-recipient"              => [],
                    "_proqyz__email-subject"                => "",
                    "_proqyz__email-content"                => "",
                    "_proqyz__email-roles"                  => ["teacher"]
                ]
            ], */
        ];

		# v2.0.3.1 
		$ST_OPTION_st_proqyz__open_ai_endpoint 	= 'st_proqyz__OPEN-AI-ENDPOINT';
		$ST_OPTION_st_proqyz__open_ai_modal		= 'st_proqyz__OPEN-AI-MODAL';
		$ST_OPTION_st_proqyz__open_ai_enable	= 'st_proqyz__OPEN-AI-ENABLE';
		$ST_OPTION_st_proqyz__open_ai_apikey	= 'st_proqyz__OPEN-AI-APIKEY';

		# v2.1.0 - Database version tracking
		$ST_OPTION_st_proqyz__db_version		= 'st_proqyz__db-version';
		$ST_OPTION_st_proqyz__migration_status	= 'st_proqyz__migration-status';
	
	}

	private function version_fix(){
		global $st_version_key, $st_maintenance_key;
		$get_pre_version 		= get_option($st_version_key, '1.0.0');
		$get_pre_fix_version	= get_option($st_maintenance_key,'1.0.0');

		if(version_compare($this->version, $get_pre_version, '>')){
			# make the fix
			// $this->rename_tables();
			$this->set_options_data();
		}

		// Initialize database version tracking (v2.1.0+)
		$this->init_db_version();
	}

	private function default_options() {
		$this->define( 'ST_PROQYZ_SPEAKING_AI_EVALUAION', 'true' );
	}

	/**
	 * Initialize database version tracking
	 * 
	 * Tracks which database schema version is in use:
	 * - v1: Uses st_proqyz_quiz_progress table (legacy, slow)
	 * - v2: Uses st_proqyz_progress_submissions + meta tables (optimized)
	 * 
	 * @since 2.1.0
	 */
	private function init_db_version() {
		global $ST_OPTION_st_proqyz__db_version, $ST_OPTION_st_proqyz__migration_status;

		// Get current DB version
		$current_db_version = get_option($ST_OPTION_st_proqyz__db_version, '1.0');

		// If not set, initialize to v1 (existing installations)
		if ($current_db_version === '1.0') {
			update_option($ST_OPTION_st_proqyz__db_version, '1.0');
			update_option($ST_OPTION_st_proqyz__migration_status, 'not_started');
		}

		// Allow upgrade to v2 via filter
		$allow_v2_upgrade = apply_filters('proqyz_allow_db_v2_upgrade', false);
		
		if ($allow_v2_upgrade && $current_db_version === '1.0') {
			// Mark as ready for migration
			update_option($ST_OPTION_st_proqyz__migration_status, 'ready_for_migration');
		}
	}


    /**
	 * Register custom tables within $wpdb object.
	 */
	private function define_tables() {
		global $wpdb;

		
		$table_details = []; 
		if( ST_PROQYZ_VERSION >= '3.0.0') {

			/**
			 * ===================================================================
			 * V3 TABLES - Migration from v2 to v3 with Quiz/Course Versioning
			 * @since 2.1.0
			 * ===================================================================
			 */

			/**
			* v3 Progress Submissions Table
			* Same structure as v2, but with v3 prefix for safe migration
			*/
			$table_details[] = array(
			   'name' => $wpdb->prefix.'st_proqyz_v3_progress_submissions',
			   'columns' => array(
				   'ID' => 'bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT',
				   'user_id' => 'bigint(20) UNSIGNED NOT NULL',
				   'quiz_category' => 'varchar(191) NOT NULL DEFAULT ""',
				   'session_type' => 'varchar(191) NOT NULL DEFAULT ""',
				   'session_category' => 'varchar(191) NOT NULL DEFAULT ""',
				   'course_category' => 'varchar(191) DEFAULT NULL',
				   'course_id' => 'varchar(100) DEFAULT NULL',
				   'topic_id' => 'varchar(100) DEFAULT NULL',
				   'lesson_id' => 'varchar(100) DEFAULT NULL',
				   'api_id' => 'varchar(100) NOT NULL',
				   'session_status' => 'tinyint(3) UNSIGNED NOT NULL DEFAULT 0',
				   'review' => 'tinyint(1) UNSIGNED NOT NULL DEFAULT 0',
				   'status' => 'tinyint(3) UNSIGNED NOT NULL DEFAULT 1',
				   'date_created' => 'bigint(20) UNSIGNED NOT NULL',
				   'date_modified' => 'bigint(20) UNSIGNED DEFAULT NULL',
			   ),
			   'indexes' => array(
				   'idx_user' => '(`user_id`) USING BTREE',
				   'idx_quiz_cat' => '(`quiz_category`) USING BTREE',
				   'idx_session_type' => '(`session_type`, `session_category`) USING BTREE',
				   'idx_session_cat' => '(`session_category`) USING BTREE',
				   'idx_date' => '(`date_created`) USING BTREE',
				   'idx_status' => '(`status`, `session_status`) USING BTREE',
				   'idx_user_session' => '(`user_id`, `session_type`, `session_category`) USING BTREE',
				   'idx_course_lesson' => '(`course_id`, `lesson_id`, `user_id`) USING BTREE',
				   'idx_api_user' => '(`api_id`, `user_id`, `status`) USING BTREE',
				   'idx_user_date' => '(`user_id`, `date_created`) USING BTREE',
			   ),
			   'engine' => 'InnoDB'
		   	);

			/**
			 * v3 Progress Submissions Meta Table
			 * Stores large serialized data (quiz, session_detail, json, score)
			 */
			$table_details[] = array(
				'name' => $wpdb->prefix.'st_proqyz_v3_progress_submissions_meta',
				'columns' => array(
					'meta_id' => 'bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT',
					'submission_id' => 'bigint(20) UNSIGNED NOT NULL',
					'meta_key' => 'varchar(191) NOT NULL',
					'meta_value' => 'longtext',
					'created_at' => 'bigint(20) UNSIGNED NOT NULL',
				),
				'indexes' => array(
					'idx_submission' => '(`submission_id`) USING BTREE',
					'idx_meta_key' => '(`meta_key`) USING BTREE',
					'idx_submission_key' => '(`submission_id`, `meta_key`) USING BTREE',
				),
				'engine' => 'InnoDB'
			);

			/**
			 * v3 Progress Meta Submissions Table
			 * Stores section-level progress data for speaking/writing quizzes
			 */
			$table_details[] = array(
				'name' => $wpdb->prefix.'st_proqyz_v3_progress_meta_submissions',
				'columns' => array(
					'ID' => 'bigint(20) NOT NULL AUTO_INCREMENT',
					'user_id' => 'int(11) NOT NULL',
					'session_type' => 'varchar(255) NOT NULL',
					'session_id' => 'varchar(255) NOT NULL',
					'quiz_id' => 'varchar(512) NOT NULL',
					'section_id' => 'varchar(512) NOT NULL',
					'question_ids' => 'varchar(512) NOT NULL',
					'question_intervals' => 'varchar(512) NOT NULL',
					'json' => 'longtext NOT NULL',
					'filename' => 'varchar(255) NOT NULL',
					'completed' => 'int(11) NOT NULL',
					'status' => 'int(11) NOT NULL',
					'date' => 'int(11) NOT NULL'
				),
				'indexes' => array(
					'idx_user' => '(`user_id`) USING BTREE',
					'idx_quiz' => '(`quiz_id`) USING BTREE',
					'idx_section' => '(`section_id`) USING BTREE',
					'idx_session' => '(`session_type`, `session_id`) USING BTREE',
					'idx_date' => '(`date`) USING BTREE',
				),
				'engine' => 'InnoDB'
			);

			/**
			 * v3 Submissions Versioning Table
			 * NEW: Stores unique quiz/course versions to eliminate redundancy
			 * 
			 * This table stores unique versions of quiz and course data.
			 * Instead of storing the same quiz data 1000 times (one per submission),
			 * we store it once and reference it by version_id.
			 * 
			 * Benefits:
			 * - 50-90% reduction in database size
			 * - Single source of truth for quiz/course data
			 * - Faster queries (smaller meta table)
			 * 
			 * @since 2.1.0
			 */
			$table_details[] = array(
				'name' => $wpdb->prefix.'st_proqyz_v3_submissions_versioning',
				'columns' => array(
					'version_id' => 'bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT',
					'meta_key' => 'varchar(191) NOT NULL',
					'meta_data_id' => 'varchar(100) NOT NULL',
					'meta_version' => 'varchar(100) NOT NULL',
					'meta_value' => 'longtext NOT NULL',
					'meta_hash' => 'varchar(64) NOT NULL',
					'created_at' => 'bigint(20) UNSIGNED NOT NULL',
					'updated_at' => 'bigint(20) UNSIGNED DEFAULT NULL',
					'usage_count' => 'bigint(20) UNSIGNED NOT NULL DEFAULT 0',
				),
				'indexes' => array(
					'idx_meta_key' => '(`meta_key`) USING BTREE',
					'idx_meta_data_id' => '(`meta_data_id`) USING BTREE',
					'idx_meta_hash' => '(`meta_hash`) USING BTREE',
					'idx_created_at' => '(`created_at`) USING BTREE',
				),
				'unique_indexes' => array(
					'idx_unique_version' => '(`meta_key`, `meta_data_id`, `meta_version`)',
				),
				'engine' => 'InnoDB'
			);

			/**
			 * v3 Progress Submissions User Response Table
			 * Dedicated table for storing user response data (json meta_key)
			 * 
			 * Separates large json data from submissions_meta table for better organization.
			 * This table stores the serialized report_stats data containing:
			 * - quiz timing information
			 * - user answers
			 * - audio time (for listening)
			 * 
			 * Benefits:
			 * - Reduces submissions_meta table size
			 * - Better table organization
			 * - Faster queries on meta table (smaller size)
			 * 
			 * Note: Unlike quiz versioning, this data is unique per submission (not redundant).
			 * 
			 * @since 2.1.0
			 */
			$table_details[] = array(
				'name' => $wpdb->prefix.'st_proqyz_v3_progress_submissions_user_response',
				'columns' => array(
					'ID' => 'bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT',
					'submission_id' => 'bigint(20) UNSIGNED NOT NULL',
					'response_data' => 'longtext NOT NULL COMMENT \'Serialized user response data (report_stats)\'',
					'created_at' => 'bigint(20) UNSIGNED NOT NULL',
					'updated_at' => 'bigint(20) UNSIGNED DEFAULT NULL',
				),
				'indexes' => array(
					'idx_submission' => '(`submission_id`) USING BTREE',
					'idx_created_at' => '(`created_at`) USING BTREE',
				),
				'unique_indexes' => array(
					'idx_unique_submission' => '(`submission_id`)',
				),
				'engine' => 'InnoDB'
			);

			/**
			 * v3 Progress Submissions Session Table
			 * Dedicated table for storing session detail data (session_detail meta_key)
			 * 
			 * Separates large session data from submissions_meta table for better organization.
			 * This table stores the serialized session object containing:
			 * - Course information
			 * - Session metadata
			 * - Quiz context
			 * 
			 * Benefits:
			 * - Reduces submissions_meta table size
			 * - Better table organization
			 * - Faster queries on meta table (smaller size)
			 * 
			 * Note: Unlike quiz versioning, this data is unique per submission (not redundant).
			 * 
			 * @since 2.1.0
			 */
			$table_details[] = array(
				'name' => $wpdb->prefix.'st_proqyz_v3_progress_submissions_session',
				'columns' => array(
					'ID' => 'bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT',
					'submission_id' => 'bigint(20) UNSIGNED NOT NULL',
					'session_data' => 'longtext NOT NULL COMMENT \'Serialized session detail data\'',
					'created_at' => 'bigint(20) UNSIGNED NOT NULL',
					'updated_at' => 'bigint(20) UNSIGNED DEFAULT NULL',
				),
				'indexes' => array(
					'idx_submission' => '(`submission_id`) USING BTREE',
					'idx_created_at' => '(`created_at`) USING BTREE',
				),
				'unique_indexes' => array(
					'idx_unique_submission' => '(`submission_id`)',
				),
				'engine' => 'InnoDB'
			);

			/**
			 * v3 Progress Submissions Score Table
			 * Dedicated table for storing score data (score meta_key)
			 * 
			 * Separates large score data from submissions_meta table for better organization.
			 * This table stores the serialized score object containing:
			 * - Quiz scores (correct, wrong, unattempt)
			 * - Task-specific scores (for writing/speaking)
			 * - Overall scores and bands
			 * - Score breakdowns
			 * 
			 * Benefits:
			 * - Reduces submissions_meta table size
			 * - Better table organization
			 * - Faster queries on meta table (smaller size)
			 * - Easier to query and analyze scores
			 * 
			 * Note: This data is unique per submission (not redundant).
			 * 
			 * @since 2.1.0
			 */
			$table_details[] = array(
				'name' => $wpdb->prefix.'st_proqyz_v3_progress_submissions_score',
				'columns' => array(
					'ID' => 'bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT',
					'submission_id' => 'bigint(20) UNSIGNED NOT NULL',
					'user_id' => 'bigint(20) UNSIGNED NOT NULL COMMENT \'User ID for quick search and delete queries\'',
					'score_data' => 'longtext NOT NULL COMMENT \'Serialized score data (JSON or serialized array)\'',
					'created_at' => 'bigint(20) UNSIGNED NOT NULL',
					'updated_at' => 'bigint(20) UNSIGNED DEFAULT NULL',
				),
				'indexes' => array(
					'idx_submission' => '(`submission_id`) USING BTREE',
					'idx_user' => '(`user_id`) USING BTREE',
					'idx_created_at' => '(`created_at`) USING BTREE',
					'idx_user_created' => '(`user_id`, `created_at`) USING BTREE',
				),
				'unique_indexes' => array(
					'idx_unique_submission' => '(`submission_id`)',
				),
				'engine' => 'InnoDB'
			);

			/**
			 * v3 Submissions Evaluation Metadata Table
			 * Usermeta-like table for storing session-level metadata
			 * 
			 * Similar to WordPress usermeta table, but designed for session-specific data.
			 * This table allows storing flexible metadata associated with sessions and users.
			 * 
			 * Use cases:
			 * - Session preferences and settings
			 * - Session-level flags and statuses
			 * - Custom session attributes
			 * - Temporary session data
			 * - Session analytics data
			 * - Evaluation-related metadata
			 * 
			 * Benefits:
			 * - Flexible key-value storage for sessions
			 * - Efficient lookups by session_id, user_id, or meta_key
			 * - Supports multiple meta entries per session
			 * - Timestamps for tracking creation and updates
			 * 
			 * @since 2.1.0
			 */
			$table_details[] = array(
				'name' => $wpdb->prefix.'st_proqyz_v3_submissions_evaluation_meta',
				'columns' => array(
					'meta_id' => 'bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT',
					'session_id' => 'varchar(100) NOT NULL COMMENT \'Session identifier\'',
					'user_id' => 'bigint(20) UNSIGNED NOT NULL COMMENT \'User ID associated with the session\'',
					'meta_key' => 'varchar(191) NOT NULL COMMENT \'Metadata key\'',
					'meta_value' => 'longtext COMMENT \'Metadata value (serialized if needed)\'',
					'created_at' => 'bigint(20) UNSIGNED NOT NULL',
					'updated_at' => 'bigint(20) UNSIGNED DEFAULT NULL',
				),
				'indexes' => array(
					'idx_session_id' => '(`session_id`) USING BTREE',
					'idx_user_id' => '(`user_id`) USING BTREE',
					'idx_meta_key' => '(`meta_key`) USING BTREE',
					'idx_session_key' => '(`session_id`, `meta_key`) USING BTREE',
					'idx_user_session' => '(`user_id`, `session_id`) USING BTREE',
					'idx_created_at' => '(`created_at`) USING BTREE',
				),
				'engine' => 'InnoDB'
			);

			/**
			 * v3 Submissions Review Table
			 * Stores review records for submissions
			 */
			$table_details[] = array(
				'name' => $wpdb->prefix.'st_proqyz_v3_submissions_review',
				'columns' => array(
					'ID' => 'bigint(10) NOT NULL AUTO_INCREMENT',
					'result_id' => 'int(20) NOT NULL',
					'user_id' => 'bigint(10) NOT NULL',
					'section_id' => 'varchar(255) NOT NULL',
					'status' => 'int(1) NOT NULL'
				),
				'engine' => 'InnoDB'
			);
			/**
			 * v3 Submissions Review Meta Table
			 * Stores review metadata
			 */
			$table_details[] = array(
				'name' => $wpdb->prefix.'st_proqyz_v3_submissions_review_meta',
				'columns' => array(
					'ID' => 'bigint(20) NOT NULL AUTO_INCREMENT',
					'review_id' => 'bigint(10) NOT NULL',
					'meta_key' => 'varchar(255) NOT NULL',
					'meta_value' => 'longtext NOT NULL',
					'meta_status' => 'int(1) NOT NULL'
				),
				'indexes' => array(
					'idx_review_id' => '(`review_id`) USING BTREE',
					'idx_meta_key' => '(`meta_key`) USING BTREE'
				),
				'engine' => 'InnoDB'
			);
		
		}

		// fullmock tests progress table (all versions)
		// v1, v2, v3
		$table_details[] = array(
			'name' => $wpdb->prefix.'st_proqyz_fullmock_tests_progress',
			'columns' => array(
				'ID' => 'bigint(20) NOT NULL AUTO_INCREMENT',
				'user_id' => 'bigint(20) NOT NULL',
				'reading' => 'bigint(20) NOT NULL',
				'listening' => 'bigint(20) NOT NULL',
				'writing' => 'int NOT NULL',
				'speaking' => 'int NOT NULL',
				'course_id' => 'varchar(255) NOT NULL',
				'lesson_id' => 'varchar(255) NOT NULL',
				'course_meta' => 'longtext NOT NULL',
				'date' => 'varchar(255) NOT NULL',
				'status' => 'int(1) NOT NULL'
			),
			'indexes' => array(
				'idx_user' => '(`user_id`) USING BTREE',
				'idx_reading' => '(`reading`) USING BTREE',
				'idx_listening' => '(`listening`) USING BTREE',
				'idx_writing' => '(`reading`) USING BTREE',
				'idx_speaking' => '(`reading`) USING BTREE',
				'idx_date' => '(`date`) USING BTREE',
				'idx_course' => '(`course_id`,`lesson_id`) USING BTREE',
			)
		);

		$table_details[] = array(
			'name' => $wpdb->prefix.'st_proqyz_groups',
			'columns' => array(
				'ID' => 'bigint(20) NOT NULL AUTO_INCREMENT',
				'group_title' => 'varchar(256) NOT NULL',
				'group_slug' => 'varchar(256) NOT NULL',
				'course_ids' => 'longtext NOT NULL',
				'student_ids' => 'longtext NOT NULL',
				'teacher_ids' => 'longtext NOT NULL',
				'date_of_publish' => 'bigint(20) NOT NULL',
				'status' => 'int(11) NOT NULL DEFAULT 0'
			)
		);

		// Loop through each table
		foreach ($table_details as $table_detail) {
			$table_name = $table_detail['name'];
			$columns    = $table_detail['columns'];
			$indexes    = isset($table_detail['indexes']) ? $table_detail['indexes'] : array();
			$unique_indexes = isset($table_detail['unique_indexes']) ? $table_detail['unique_indexes'] : array();
			$engine     = !empty($table_detail['engine']) ? $table_detail['engine'] : 'InnoDB';

			// Determine primary key column (first AUTO_INCREMENT column or 'ID')
			$primary_key = 'ID';
			foreach ($columns as $column_name => $column_definition) {
				if (stripos($column_definition, 'AUTO_INCREMENT') !== false) {
					$primary_key = $column_name;
					break;
				}
			}

			// Check if table exists
			$query  = $wpdb->prepare("SHOW TABLES LIKE %s", $wpdb->esc_like($table_name));
			$result = $wpdb->get_var($query);

			if ($result !== $table_name) {
				// Create new table
				$charset_collate = $wpdb->get_charset_collate();
				$sql = "CREATE TABLE $table_name (";

				// Add columns
				foreach ($columns as $column_name => $column_definition) {
					$sql .= "`$column_name` $column_definition, ";
				}

				// Add primary key
				$sql .= "PRIMARY KEY (`$primary_key`)";

				// Add regular indexes
				foreach ($indexes as $index_name => $index_definition) {
					$sql .= ", KEY `$index_name` $index_definition";
				}

				// Add unique indexes
				foreach ($unique_indexes as $index_name => $index_definition) {
					$sql .= ", UNIQUE KEY `$index_name` $index_definition";
				}

				$sql .= ") ENGINE=$engine $charset_collate;";

				// Log table creation attempt
				if (defined('WP_DEBUG') && WP_DEBUG) {
					error_log("ProQyz: Creating table {$table_name}");
					error_log("SQL: " . $sql);
				}

				require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
				$result = dbDelta($sql);

				// Log result
				if (defined('WP_DEBUG') && WP_DEBUG) {
					error_log("ProQyz: dbDelta result for {$table_name}: " . print_r($result, true));
					
					// Verify table was created
					$verify = $wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $wpdb->esc_like($table_name)));
					if ($verify === $table_name) {
						error_log("ProQyz: ✓ Table {$table_name} created successfully");
					} else {
						error_log("ProQyz: ✗ Table {$table_name} creation FAILED");
						error_log("ProQyz: Last error: " . $wpdb->last_error);
					}
				}

			} else {
				// Table already exists -> check structure
				$sql_describe = "DESCRIBE $table_name";
				$current_columns = $wpdb->get_results($sql_describe, ARRAY_A);

				// Ensure all required columns exist
				foreach ($columns as $column_name => $column_definition) {
					$column_found = false;
					foreach ($current_columns as $current_column) {
						if ($current_column['Field'] === $column_name) {
							$column_found = true;
							break;
						}
					}
					if (!$column_found) {
						$sql_alter = "ALTER TABLE $table_name ADD COLUMN `$column_name` $column_definition";
						$wpdb->query($sql_alter);
					}
				}

				// Ensure indexes exist
				$current_indexes = $wpdb->get_results("SHOW INDEX FROM $table_name", ARRAY_A);
				$existing_indexes = array_column($current_indexes, 'Key_name');
				
				// Add regular indexes
				foreach ($indexes as $index_name => $index_definition) {
					if (!in_array($index_name, $existing_indexes)) {
						$wpdb->query("ALTER TABLE $table_name ADD KEY `$index_name` $index_definition");
					}
				}
				
				// Add unique indexes
				foreach ($unique_indexes as $index_name => $index_definition) {
					if (!in_array($index_name, $existing_indexes)) {
						$wpdb->query("ALTER TABLE $table_name ADD UNIQUE KEY `$index_name` $index_definition");
					}
				}

				// Ensure engine matches
				$current_engine = $wpdb->get_var("SELECT ENGINE FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = '$table_name'");
				if (strtoupper($current_engine) !== strtoupper($engine)) {
					$wpdb->query("ALTER TABLE $table_name ENGINE=$engine");
				}
			}
		}
	}

	/**
	 * since @1.0.1
	 * version  versions < @1.1.0
	 */
	private function set_options_data(){
		global 
			$ST_OPTION_st_proqyz__license_key, 
			$ST_OPTION_st_proqyz__enable_key,
			$ST_OPTION_st_proqyz__auth_redirect_enable_key,
			$ST_OPTION_st_proqyz__auth_signup_url_key,
			$ST_OPTION_st_proqyz__auth_signin_url_key,
			$ST_OPTION_st_proqyz__auth_ielts_account_complete;
			
		global $ST_OPTION_st_proqyz__IELTS_LMS, $ST_OPTION_st_proqyz__GOV_LMS;
	
		// Get old option values
		$old_lms_license_key = get_option('st_pro-quiz-lms-api-key'); // st_pro-quiz-lms-api-key
		$old_lms_enable_key = get_option('st_proquiz-lms');
		$old_auth_redirect_enable_key = get_option('st-pro-quiz_auth-redirect-enable');
		$old_auth_signup_url_key = get_option('st-pro-quiz__auth-signup-url');
		$old_auth_signin_url_key = get_option('st-pro-quiz__auth-signin-url');
		$old_auth_ielts_account_complete_key = get_option('st_proqyz-auth-ielts-account-complete');
	
		// If old options exist, migrate their values to new options keys
		if ($old_lms_license_key !== false) {
			// Store old license key value in new option key
			update_option($ST_OPTION_st_proqyz__license_key, $old_lms_license_key);
	
			// Remove old license key option
			delete_option('st_pro-quiz-lms-api-key');
		}
	
		if ($old_lms_enable_key !== false) {
			// Store old enable key value in new option key
			update_option($ST_OPTION_st_proqyz__enable_key, $old_lms_enable_key);
	
			// Remove old enable key option
			delete_option('st_proquiz-lms');
		}
	
		if ($old_auth_redirect_enable_key !== false) {
			// Store old auth redirect enable key value in new option key
			update_option($ST_OPTION_st_proqyz__auth_redirect_enable_key, $old_auth_redirect_enable_key);
	
			// Remove old auth redirect enable key option
			delete_option('st-pro-quiz_auth-redirect-enable');
		}
	
		if ($old_auth_signup_url_key !== false) {
			// Store old auth signup URL key value in new option key
			update_option($ST_OPTION_st_proqyz__auth_signup_url_key, $old_auth_signup_url_key);
	
			// Remove old auth signup URL key option
			delete_option('st-pro-quiz__auth-signup-url');
		}
	
		if ($old_auth_signin_url_key !== false) {
			// Store old auth signin URL key value in new option key
			update_option($ST_OPTION_st_proqyz__auth_signin_url_key, $old_auth_signin_url_key);
	
			// Remove old auth signin URL key option
			delete_option('st-pro-quiz__auth-signin-url');
		}
	
		if ($old_auth_ielts_account_complete_key !== false) {
			// Store old auth IELTS account complete key value in new option key
			update_option($ST_OPTION_st_proqyz__auth_ielts_account_complete, $old_auth_ielts_account_complete_key);
	
			// Remove old auth IELTS account complete key option
			delete_option('st_proqyz-auth-ielts-account-complete');
		}


		// auto enable
		update_option($ST_OPTION_st_proqyz__IELTS_LMS,1);
        update_option($ST_OPTION_st_proqyz__GOV_LMS,1);

	}
	
	

    /**
	 * Define constant if not already set.
	 *
	 * @param string      $name  Constant name.
	 * @param string|bool $value Constant value.
	 */
	private function define( $name, $value ) {
		if ( ! defined( $name ) ) {
			define( $name, $value );
		}
	}

	/**
	 * Include required core files used in admin and on the frontend.
	 */
	public function includes() {
		global 
        $ST_OPTION_st_proqyz__license_key, 
        $ST_OPTION_st_proqyz__enable_key,
        $ST_OPTION_st_proqyz__auth_redirect_enable_key,
        $ST_OPTION_st_proqyz__auth_signup_url_key,
        $ST_OPTION_st_proqyz__auth_signin_url_key,
        $ST_OPTION_st_proqyz__auth_ielts_account_complete;
        $st_proqyz_enable   = get_option($ST_OPTION_st_proqyz__enable_key,0);
        

		/**
		 * Load core helper classes
		 */
		// include_once ST_PROQYZ_ABSPATH . "includes/class-st-proqyz-submission-meta.php"; // v2 meta helpers

		/**
		 * Load admin/post_types
		 */
		include_once ST_PROQYZ_ABSPATH . "includes/admin/class-st-proqyz-post-types.php";
		include_once ST_PROQYZ_ABSPATH . "includes/admin/class-st-proqyz-post-permalinks.php"; // checked
		include_once ST_PROQYZ_ABSPATH . "includes/admin/class-st-proqyz-admin.php"; // checked
		include_once ST_PROQYZ_ABSPATH . "includes/admin/class-st-proqyz-debug-log.php"; // custom debug log (proqyz/logs, gated by st_proqyz_custom_debug_log option)

        // --- NEW ---
        // Load the new permalink settings page class.
        // We check is_admin() so this code only loads in the WordPress dashboard.
        if ( is_admin() ) {
            include_once ST_PROQYZ_ABSPATH . "includes/admin/class-st-proqyz-admin-settings.php";
            // Note: Migration admin is now loaded at root level (spacetree/includes/admin/)
        }
        // --- END NEW ---

		/**
		 * Load public/
		 */
		
		include_once ST_PROQYZ_ABSPATH . "includes/integrations/woocommerce/woocommerce.php";
		// include_once ST_PROQYZ_ABSPATH . "includes/integrations/learndash/class-sfwd-lms-integration.php"; - deprecated (moved to external addon: proqyz-learndash)
		

		/**
		 * Load Oauth
		 */
		include_once ST_PROQYZ_ABSPATH . "includes/class-st-proqyz-oauth.php"; // checked

		/**
		 * Load public features (only if plugin is not disabled)
		 * 
		 * Two-stage unlock system:
		 * - Stage 1 (DB v1): Plugin works with v1 features (warning shown)
		 * - Stage 2 (DB v2, Plugin old): Features BLOCKED (must update plugin)
		 * - Fully Updated (DB v2, Plugin v2): All features work with v2 optimization
		 * 
		 * @since 2.1.0
		 */
		/**
		* load public restapis
		*/
		include_once ST_PROQYZ_ABSPATH . "includes/public/class-st-proqyz-public-rest-api.php";

		/**
		* load triggers
		*/
		include_once ST_PROQYZ_ABSPATH . "includes/public/filters/filters.php";

		/**
		* load helpers
		*/
		require_once ST_PROQYZ_ABSPATH .'includes/public/helpers/shortcode-helpers.php';

		/**
		* load shortcodes
		*/
		include_once ST_PROQYZ_ABSPATH . "includes/public/class-st-proqyz-public-ajax.php"; // checked

		/**
		* since 1.2.2 - fix
		* hooks
		*/
		include_once ST_PROQYZ_ABSPATH . "includes/public/hooks/hooks.php"; // checked
		include_once ST_PROQYZ_ABSPATH . "includes/public/public-shortcodes.php";

		/**
		* signup 
		*/
		include_once ST_PROQYZ_ABSPATH . "includes/class-signup-ajax.php";

		// --- NEW ---
        // Instantiate the settings class to register its hooks.
        if ( is_admin() ) {
            new ST_ProQyz_Admin_Settings();
        }
        // --- END NEW ---

	}


	/**
	 * init hooks
	 */
	public function init_hooks(){
		add_action( 'wp_enqueue_scripts', [$this, 'enqueue_scripts'] );
	}

	/**
	 * Register the JavaScript for the public-facing side of the site.
	 *
	 * @since    1.0.0
	 */
	public function enqueue_scripts() {
		/**
		 * This function is provided for demonstration purposes only.
		 *
		 * An instance of this class should be passed to the run() function
		 * defined in Ielts_Lms_Loader as all of the hooks are defined
		 * in that particular class.
		 *
		 * The Ielts_Lms_Loader will then create the relationship
		 * between the defined hooks and the functions defined in this
		 * class.
		 */
		
	}

	/**
	 * Shortcode shown when plugin update is required (Stage 2)
	 * Displayed after migration completes but before plugin update
	 * 
	 * Shows different messages:
	 * - Admins: See detailed update instructions
	 * - Regular Users: See generic "system upgrade in progress" message
	 * 
	 * @since 2.1.0
	 */
	public function plugin_update_required_shortcode() {
		if (!is_user_logged_in()) {
			return '';
		}

		ob_start();
		
		// Check if user is admin (can update plugins or manage options)
		$is_admin = current_user_can('update_plugins') || current_user_can('manage_options');
		
		if ($is_admin) {
			// Admin view - show detailed update instructions
			$update_url = admin_url('update-core.php');
			$migrate_url = admin_url('admin.php?page=st-proqyz-migrate');
			?>
			<div class="proqyz-update-required" style="background: #fff3cd; border-left: 4px solid #dc3232; padding: 20px; margin: 20px 0;">
				<h3 style="margin-top: 0; color: #856404;">🚨 Plugin Update Required (Step 2 of 2)</h3>
				<p style="font-size: 14px;">
					<strong>✓ Step 1 Complete:</strong> Your database has been migrated to v2!<br>
					<strong>⚠️ Step 2 Required:</strong> Please update the ProQyz plugin to unlock all features.
				</p>
				<p>
					<a href="<?php echo esc_url($update_url); ?>" 
						class="button button-primary" 
						style="background: #dc3232; border-color: #dc3232; color: white; text-decoration: none; padding: 8px 16px; display: inline-block; margin-right: 10px;">
						🔄 Update Plugin to v2.1.0+
					</a>
					<?php if (current_user_can('manage_options')) : ?>
					<a href="<?php echo esc_url($migrate_url); ?>" 
						class="button button-secondary" 
						style="text-decoration: none; padding: 8px 16px; display: inline-block;">
						📊 View Migration Status
					</a>
					<?php endif; ?>
				</p>
				<p style="font-size: 13px; color: #666;">
					After updating, you'll have access to the optimized v2 features with <strong>99% faster performance</strong>.
					Same shortcodes, but optimized backend!
				</p>
			</div>
			<?php
		} else {
			// Regular user view - show generic upgrade message
			?>
			<div class="proqyz-system-upgrade" style="background: #e7f3ff; border-left: 4px solid #0073aa; padding: 20px; margin: 20px 0; text-align: center;">
				<h3 style="margin-top: 0; color: #0073aa;">🔧 System Upgrade in Progress</h3>
				<p style="font-size: 14px; color: #333; margin: 15px 0;">
					We are currently upgrading our system to bring you better performance and new features.
				</p>
				<p style="font-size: 14px; color: #555; margin: 10px 0;">
					Please hold back while we complete this upgrade. We'll be back shortly!
				</p>
				<p style="font-size: 13px; color: #666; margin-top: 15px;">
					Thank you for your patience. 🙏
				</p>
			</div>
			<?php
		}
		
		return ob_get_clean();
	}

}