<?php 
/**
 * v2.1.0
 * status: completed (testing required - its copy of vscode php)
 * ilms-submit-writing-review
 */

// v2.1.0
// create utils function for submissions meta for checking if meta exists or not  
// if not exists then add it
// if exists then update it
function proqyz_utils_submissions_meta_v2($submission_id, $meta_key, $meta_value) {
    global $wpdb, $table_proqyz_v3_progress_submissions_meta;
    $meta_exists = $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM {$table_proqyz_v3_progress_submissions_meta} WHERE submission_id = %d AND meta_key = %s", $submission_id, $meta_key));
    if($meta_exists) {
        $wpdb->update($table_proqyz_v3_progress_submissions_meta, ['meta_value' => $meta_value], ['submission_id' => $submission_id, 'meta_key' => $meta_key]);
    } else {
        $wpdb->insert($table_proqyz_v3_progress_submissions_meta, ['submission_id' => $submission_id, 'meta_key' => $meta_key, 'meta_value' => $meta_value, 'created_at' => date("U")]);
    }
}

// unitil function for score data exists or not using submission_id to store score data or update it or insert it 
function proqyz_utils_submissions_score_v3($submission_id, $user_id, $score_data) {
    global $wpdb, $table_proqyz_v3_progress_submissions_score;
    $score_exists = $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM {$table_proqyz_v3_progress_submissions_score} WHERE submission_id = %d AND user_id = %d", $submission_id, $user_id));
    if($score_exists) {
        $wpdb->update($table_proqyz_v3_progress_submissions_score, ['score_data' => $score_data, 'updated_at' => date("U")], ['submission_id' => $submission_id, 'user_id' => $user_id]);
    } else {
        $wpdb->insert($table_proqyz_v3_progress_submissions_score, ['submission_id' => $submission_id, 'user_id' => $user_id, 'score_data' => $score_data, 'created_at' => date("U")]);
    }
}

/**
* Function to find object by key and value
*
* @param array $objectsArray - Array of objects to search in
* @param string $key - The key to compare
* @param mixed $value - The value to compare with
* @return object|null - Returns the object if found, otherwise null
*/
function proqyz_findObjectByKeyValue($objectsArray, $key, $value) {
    foreach ($objectsArray as $obj) {
        if (isset($obj->$key) && $obj->$key == $value) {
            return $obj;
        }
    }
    return null; // Return null if no object is found
}

/**
 * v3.1.0
 */
add_action('wp_ajax_proqyz-submit-writing-review', 'proqyz_submit_writing_review_callback');
function proqyz_submit_writing_review_callback(){
    global $wpdb, 
	$table_proqyz_v3_progress_submissions, 
	$table_proqyz_v3_submissions_review, 
	$table_proqyz_v3_submissions_review_meta,
    $table_proqyz_v3_progress_submissions_score;

    $report_review = (object) $_POST['report'];

    //$review         = $report_review->review;
    //$review_id      = $report_review->review_id;
    $reviewer_id    = get_current_user_id();
    $result_id      = $report_review->result_id;
    $section_id     = $report_review->section_id;
    $section_order  = $report_review->section_order;
    $scores         = (array) $report_review->scores;
    $review_content = $report_review->review_content;


    $scores_tmp     = [];
    foreach( $scores as $skey => $svalue ) {
        $scores_tmp[$skey] = (int) $svalue;
    }

    # it will become array of scores like [0,0,0,0]
    $scores         = (array) $scores_tmp;

    
    $get_result = $wpdb->get_row("SELECT `user_id` FROM {$table_proqyz_v3_progress_submissions} WHERE `ID` = '$result_id' LIMIT 1");
    if( $get_result ) {
        $student_id = $get_result->user_id;
        # get review id from selected section_id
        $get_review         = $wpdb->get_row("SELECT `ID` FROM {$table_proqyz_v3_submissions_review} WHERE `result_id` = '$result_id' AND `user_id` = '$student_id' AND `status` = 1 AND `section_id` = '$section_id' LIMIT 1");
        if( !$get_review ) {

            $insert_review = $wpdb->insert($table_proqyz_v3_submissions_review, [
                "result_id"     => $result_id,
                "user_id"       => $student_id,
                "section_id"    => $section_id,
                "status"        => 1
            ]);

            if( $insert_review ) {
                $review_id = $wpdb->insert_id;
            } else {
                wp_send_json([
                    "error" => (object) [
                        "message"   => "Failed to post review",
                        "res_type"  => "error",
                        "status"    => 200
                    ]
                ]);
            }
        } else {
            $review_id = $get_review->ID;
        }

        # insert of update review meta
        $review_feedback_content_key = $wpdb->get_row("SELECT `meta_value`, `ID` FROM {$table_proqyz_v3_submissions_review_meta} WHERE `meta_key` = 'review-feedback-content' AND `review_id` = '$review_id' AND `meta_status` = 1 LIMIT 1");
        if( $review_feedback_content_key ) { 
            $wpdb->update($table_proqyz_v3_submissions_review_meta, [
                "meta_value"    => $wpdb->_real_escape(stripslashes($review_content)),
            ], [
                "ID"            => $review_feedback_content_key->ID,
                "meta_key"      => "review-feedback-content",
                "meta_status"   => 1,
                "review_id"     => $review_id

            ]);
        } else {
            $wpdb->insert($table_proqyz_v3_submissions_review_meta, [
                "meta_value"    => $wpdb->_real_escape(stripslashes($review_content)),
                "meta_key"      => "review-feedback-content",
                "meta_status"   => 1,
                "review_id"     => $review_id
            ]);
        }

        
        # 2.) review scores
        $review_feedback_score_key = $wpdb->get_row("SELECT `meta_value`, `ID` FROM {$table_proqyz_v3_submissions_review_meta} WHERE `meta_key` = 'review-scores' AND `review_id` = '$review_id' AND `meta_status` = 1 LIMIT 1");
        if( $review_feedback_score_key ) { 
            $wpdb->update($table_proqyz_v3_submissions_review_meta, [
                "meta_value"    => json_encode($scores),
            ], [
                "ID"            => $review_feedback_score_key->ID,
                "meta_key"      => "review-scores",
                "meta_status"   => 1,
                "review_id"     => $review_id

            ]);
        } else {
            $wpdb->insert($table_proqyz_v3_submissions_review_meta, [
                "meta_value"    => json_encode($scores),
                "meta_key"      => "review-scores",
                "meta_status"   => 1,
                "review_id"     => $review_id
            ]);
        }

        # 3.) review writter
        $review_feedback_key = $wpdb->get_row("SELECT `meta_value`, `ID` FROM {$table_proqyz_v3_submissions_review_meta} WHERE `meta_key` = 'reviewer' AND `review_id` = '$review_id' AND `meta_status` = 1 LIMIT 1");
        if( $review_feedback_key ) { 
            $wpdb->update($table_proqyz_v3_submissions_review_meta, [
                "meta_value"    => $reviewer_id,
            ], [
                "ID"            => $review_feedback_key->ID,
                "meta_key"      => "reviewer",
                "meta_status"   => 1,
                "review_id"     => $review_id

            ]);
        } else {
            $wpdb->insert($table_proqyz_v3_submissions_review_meta, [
                "review_id"     => $review_id,
                "meta_key"      => "reviewer",
                "meta_value"    => $reviewer_id,
                "meta_status"   => 1
            ]);
        }
        

        # mark as reviewed and email if possible
        $wpdb->update($table_proqyz_v3_progress_submissions, [
            'review'    => 1,
            'date_modified' => date("U")
        ], ['ID' => $result_id]);

        # email logic
        apply_filters('proqyz_quiz__on_evaluation_writing', [
            "user_id"               => $student_id,
            "reviewer_id"           => $reviewer_id,
            "result_id"             => $result_id
        ]);

        wp_send_json([
            "success" => (object) [
                "message" => "Review posted successfully",
                "reload"  => $get_review? false : true  
            ]
        ]);

    } else {
        wp_send_json([
            "error" => (object) [
                "message"   => "Result not found, reload page",
                "res_type"  => "error",
                "status"    => 200
            ]
        ]);
    }
        


}

/**
 * v3.1.0
 */
add_action('wp_ajax_proqyz-instructor-evaluation-speaking', 'proqyz_submit_speaking_review_callback');
function proqyz_submit_speaking_review_callback(){
    global $wpdb, 
	$table_proqyz_v3_progress_submissions, 
	$table_proqyz_v3_submissions_review, 
	$table_proqyz_v3_submissions_review_meta,
    $table_proqyz_v3_progress_submissions_score;
    
    $report_review = (object) $_POST['report'];

    //$review         = $report_review->review;
    //$review_id      = $report_review->review_id;
    $reviewer_id    = get_current_user_id();
    $result_id      = $report_review->result_id;
    $scores         = (array) $report_review->scores;
    $review_content = $report_review->review_content;
    $review_status  = (int) $report_review->review_enable;

    $scores_tmp     = [];
    foreach( $scores as $skey => $svalue ) {
        $scores_tmp[$skey] = (int) $svalue;
    }

    # it will become array of scores like [0,0,0,0]
    $scores         = (array) $scores_tmp;

    
    $get_result = $wpdb->get_row("SELECT `user_id` FROM {$table_proqyz_v3_progress_submissions} WHERE `ID` = '$result_id' LIMIT 1");
    if( $get_result ) {
        $student_id = $get_result->user_id;
        
        # get review id from selected section_id
        $get_review         = $wpdb->get_row("SELECT `ID` FROM {$table_proqyz_v3_submissions_review} WHERE `result_id` = '$result_id' AND `user_id` = '$student_id' AND `status` = 1 LIMIT 1");
        if( !$get_review ) {

            $insert_review = $wpdb->insert($table_proqyz_v3_submissions_review, [
                "result_id"     => $result_id,
                "user_id"       => $student_id,
                "section_id"    => '',
                "status"        => 1
            ]);

            if( $insert_review ) {
                $review_id = $wpdb->insert_id;
            } else {
                wp_send_json([
                    "error" => (object) [
                        "message"   => "Failed to post review",
                        "res_type"  => "error",
                        "status"    => 200
                    ]
                ]);
            }
        } else {
            $review_id = $get_review->ID;
        }

        # insert of update review meta

        # 1.) review content, status
        $review_feedback_key = $wpdb->get_row("SELECT `meta_value`, `ID` FROM {$table_proqyz_v3_submissions_review_meta} WHERE `meta_key` = 'review-feedback-enable' AND `review_id` = '$review_id' AND `meta_status` = 1 LIMIT 1");
        if( $review_feedback_key ) { 
            $wpdb->update($table_proqyz_v3_submissions_review_meta, [
                "meta_value"    => $review_status,
            ], [
                "ID"            => $review_feedback_key->ID,
                "meta_key"      => "review-feedback-enable",
                "meta_status"   => 1,
                "review_id"     => $review_id

            ]);
        } else {
            $wpdb->insert($table_proqyz_v3_submissions_review_meta, [
                "review_id"     => $review_id,
                "meta_value"    => $review_status,
                "meta_key"      => "review-feedback-enable",
                "meta_status"   => 1
            ]);
        }

        $review_feedback_content_key = $wpdb->get_row("SELECT `meta_value`, `ID` FROM {$table_proqyz_v3_submissions_review_meta} WHERE `meta_key` = 'review-feedback-content' AND `review_id` = '$review_id' AND `meta_status` = 1 LIMIT 1");
        if( $review_feedback_content_key ) { 
            $wpdb->update($table_proqyz_v3_submissions_review_meta, [
                "meta_value"    => $review_status? $wpdb->_real_escape(stripslashes($review_content)) : '',
            ], [
                "ID"            => $review_feedback_content_key->ID,
                "meta_key"      => "review-feedback-content",
                "meta_status"   => 1,
                "review_id"     => $review_id

            ]);
        } else {
            $wpdb->insert($table_proqyz_v3_submissions_review_meta, [
                "meta_value"    => $review_status? $wpdb->_real_escape(stripslashes($review_content)) : '',
                "meta_key"      => "review-feedback-content",
                "meta_status"   => 1,
                "review_id"     => $review_id
            ]);
        }

        
        # 2.) review scores
        $review_feedback_score_key = $wpdb->get_row("SELECT `meta_value`, `ID` FROM {$table_proqyz_v3_submissions_review_meta} WHERE `meta_key` = 'review-scores' AND `review_id` = '$review_id' AND `meta_status` = 1 LIMIT 1");
        if( $review_feedback_score_key ) { 
            $wpdb->update($table_proqyz_v3_submissions_review_meta, [
                "meta_value"    => json_encode($scores),
            ], [
                "ID"            => $review_feedback_score_key->ID,
                "meta_key"      => "review-scores",
                "meta_status"   => 1,
                "review_id"     => $review_id

            ]);
        } else {
            $wpdb->insert($table_proqyz_v3_submissions_review_meta, [
                "meta_value"    => json_encode($scores),
                "meta_key"      => "review-scores",
                "meta_status"   => 1,
                "review_id"     => $review_id
            ]);
        }

        # 3.) review writter
        $review_feedback_key = $wpdb->get_row("SELECT `meta_value`, `ID` FROM {$table_proqyz_v3_submissions_review_meta} WHERE `meta_key` = 'reviewer' AND `review_id` = '$review_id' AND `meta_status` = 1 LIMIT 1");
        if( $review_feedback_key ) { 
            $wpdb->update($table_proqyz_v3_submissions_review_meta, [
                "meta_value"    => $reviewer_id,
            ], [
                "ID"            => $review_feedback_key->ID,
                "meta_key"      => "reviewer",
                "meta_status"   => 1,
                "review_id"     => $review_id

            ]);
        } else {
            $wpdb->insert($table_proqyz_v3_submissions_review_meta, [
                "review_id"     => $review_id,
                "meta_key"      => "reviewer",
                "meta_value"    => $reviewer_id,
                "meta_status"   => 1
            ]);
        }

        # mark as reviewed and email if possible
        $wpdb->update($table_proqyz_v3_progress_submissions, [
            'review'            => 1,
            'date_modified'     => date("U")
        ], ['ID' => $result_id]);

        apply_filters('proqyz_quiz__on_evaluation_speaking', [
            "user_id"               => $student_id,
            "reviewer_id"           => $reviewer_id,
            "result_id"             => $result_id
        ]);


        wp_send_json([
            "success" => (object) [
                "message" => "Review posted successfully"
            ]
        ]);

    } else {
        wp_send_json([
            "error" => (object) [
                "message"   => "Result not found, reload page",
                "res_type"  => "error",
                "status"    => 200
            ]
        ]);
    }

}






/**
 * v3.1.0 
 * @action proqyz__writing-ai-evaluation
 */
add_action('wp_ajax_proqyz__writing-ai-evaluation', 'proqyz__writing_ai_evaluation_callback');
function proqyz__writing_ai_evaluation_callback() {
    
    if (
        isset($_POST['section_id']) && isset($_POST['result_id']) &&
        !empty($_POST['section_id']) && !empty($_POST['result_id'])
    ) {
        $result_id      = sanitize_text_field($_POST['result_id']);
        $section_id     = sanitize_text_field($_POST['section_id']);

        global $wpdb, 
        $table_proqyz_v3_progress_submissions, 
        $table_proqyz_v3_progress_submissions_meta,
        $table_proqyz_v3_submissions_review, 
        $table_proqyz_v3_submissions_review_meta,
        $table_proqyz_v3_progress_submissions_user_response,
        $table_proqyz_v3_submissions_versioning; 

        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; 
        $ST_OPTION_st_proqyz__open_ai_endpoint__option_value    = get_option($ST_OPTION_st_proqyz__open_ai_endpoint, 'https://api.openai.com/v1/completions');
        $ST_OPTION_st_proqyz__open_ai_modal__option_value       = get_option($ST_OPTION_st_proqyz__open_ai_modal, 'gpt-4');
        $ST_OPTION_st_proqyz__open_ai_enable__option_value      = get_option($ST_OPTION_st_proqyz__open_ai_enable, 0);
        $ST_OPTION_st_proqyz__open_ai_apikey                    = get_option($ST_OPTION_st_proqyz__open_ai_apikey, '');

        if( $ST_OPTION_st_proqyz__open_ai_enable__option_value == 0 ){
            wp_send_json([
                'error'  => (object) [
                    "message" => 'AI Evaluation is not enabled'
                ]
            ]);
        }


        if( $ST_OPTION_st_proqyz__open_ai_apikey == ''){
            wp_send_json([
                'error'  => (object) [
                    "message" => 'AI Apikey is not set'
                ]
            ]);
        }


        $current_user_id = get_current_user_id();
        # match it with student_id - to ensure if student is making that request
        $get_result = $wpdb->get_row("SELECT `user_id` FROM {$table_proqyz_v3_progress_submissions} WHERE `ID` = '$result_id' LIMIT 1");
        if( !$get_result ) {
            wp_send_json([
                'error'  => (object) [
                    "message" => 'Result id with given request not found'
                ]
            ]);
        }

        # condition for checking current user detail realted to result
        $student_id = $get_result->user_id;
        // get json, quiz from individual meta tables 
        $json_data = $wpdb->get_var("SELECT `response_data` FROM {$table_proqyz_v3_progress_submissions_user_response} WHERE `submission_id` = '$result_id' LIMIT 1");
        $json_data = $json_data? (object) maybe_unserialize($json_data) : null;
        
        // get quiz version id from submissions meta table
        $sections = $wpdb->get_var("SELECT `meta_value` FROM {$table_proqyz_v3_progress_submissions_meta} WHERE `submission_id` = '$result_id' AND `meta_key` = 'sections' LIMIT 1");
        $sections = $sections? (array) maybe_unserialize($sections) : [];

        # get quiz version id from submissions meta table
        $quiz_version_id = $wpdb->get_var("SELECT `meta_value` FROM {$table_proqyz_v3_progress_submissions_meta} WHERE `submission_id` = '$result_id' AND `meta_key` = 'quiz_version_id' LIMIT 1");
        $quiz_version_id = $quiz_version_id? (int) $quiz_version_id : 0;
        if( $quiz_version_id <= 0 ) {
            wp_send_json([
                'error' => (object) [
                    'message' => 'Failed to get quiz version id',
                ]
            ]);
        } 

        # get quiz from versioning table
        $quiz_version_meta = $wpdb->get_row("SELECT `meta_value` FROM {$table_proqyz_v3_submissions_versioning} WHERE `version_id` = '$quiz_version_id' LIMIT 1");
        $quiz_version_meta = $quiz_version_meta? (object) maybe_unserialize($quiz_version_meta->meta_value) : null;
        if( !$quiz_version_meta ) {
            wp_send_json([
                'error' => (object) [
                    'message' => 'Failed to get quiz version meta',
                ]
            ]);
        }

        $quiz_payload = (object) isset($quiz_version_meta->quiz)? $quiz_version_meta->quiz : null;
        $sections_payload = (array) isset($quiz_version_meta->sections)? $quiz_version_meta->sections : [];

        if( !$json_data || count($sections) <= 0  || !$quiz_payload || count($sections_payload) <= 0 ) {
            wp_send_json([
                'error' => (object) [
                    'message' => 'Failed to get json or quiz data',
                    'sections' => $sections_payload,
                    'json_data' => $json_data,
                ]
            ]);
        }

        $user_json  = $json_data;
        $filteredArray = array_filter($sections_payload, function($object) use ($section_id) {
            return $object->_id == $section_id;
        });

        $fetched_task = !empty($filteredArray) ? reset($filteredArray) : null;
        if( !$fetched_task ) {
            wp_send_json([
                'error' => [
                    'message' => 'Failed to get task for evaluation',
                ]
            ]);
        }


        $response           = $user_json;
        $user_answers       = isset($response->answers)? (array) $response->answers : null;
        $current_question   = proqyz_findObjectByKeyValue($user_answers, 'id', $section_id);
        $fill_answer        = false;
        $user_answer        = '';
        if( $current_question ) {
            $input_type     = isset($current_question->input_type)? $current_question->input_type : '';
            $q_type         = isset($current_question->q_type)? $current_question->q_type : ''; 
            $input_class    = isset($current_question->class)? $current_question->class : ''; 
            $q_total        = isset($current_question->total)? (int) $current_question->total : 0;
            if( $input_type == "textarea" && $q_type == 'writing-essay' && $input_class == "-checked" ) {
                $fill_answer = true;
                $user_answer = isset($current_question->answer)? $current_question->answer : '';
            }  
        }

        if( !$fill_answer ) {
            wp_send_json([
                'error' => [
                    'message' => 'AI cannot evaluate an empty user task response',
                ]
            ]);
        }

        // Prepare REST API request — trigger evaluation and return "started" without waiting for OpenAI.
        // Use short timeout so we only wait for quick validation errors from REST; otherwise return "started".
        add_filter('https_ssl_verify', '__return_false');
        add_filter('https_local_ssl_verify', '__return_false');
        $url = rest_url('spacetree/proqyz/writing/ai/evaluation');
        $response = wp_remote_post($url, [
            'method'    => 'POST',
            'body'      => [
                'result_id'     => $result_id,
                'section_id'    => $section_id,
                "section"       => $fetched_task,
                "user_answer"   => $user_answer          
            ],
            'timeout'   => 120, // Short timeout: get quick errors only; don't wait for full evaluation
        ]);

        if (is_wp_error($response)) {
            // Timeout or connection error: evaluation was triggered, server may still be processing.
            wp_send_json([
                'success' => (object) [
                    'message' => 'Evaluation started. You can leave this tab; we will notify you when complete.',
                    'started' => true,
                ]
            ]);
        }

        $response_body = (object) json_decode(wp_remote_retrieve_body($response));
        if (isset($response_body->error)) {
            wp_send_json([
                "error" => $response_body->error
            ]);
        }
        if (isset($response_body->success)) {
            // Rare: REST returned within timeout (e.g. already completed or quick message).
            wp_send_json([
                "success" => $response_body->success,
                "prompt"  => isset($response_body->payload) ? $response_body->payload : null
            ]);
        }

        // Unexpected response body — treat as started (evaluation was triggered).
        wp_send_json([
            'success' => (object) [
                'message' => 'Evaluation started. You can leave this tab; we will notify you when complete.',
                'started' => true,
            ]
        ]);
    } else {
        wp_send_json([
            'error' => [
                'message' => 'Missing required parameters',
            ]
        ]);
    }
}





/**
 * v3.1.0
 * @var proqyz__speaking-ai-evaluation
 */
add_action('wp_ajax_proqyz__speaking-ai-evaluation', 'proqyz__speaking_ai_evaluation_callback');
function proqyz__speaking_ai_evaluation_callback() {
    if (!isset($_POST['result_id']) || empty($_POST['result_id'])) {
        wp_send_json([
            'error' => (object) [
                'message' => 'Missing required parameters',
            ],
        ]);
    }

    $result_id = sanitize_text_field($_POST['result_id']);
    $context   = isset($_POST['context']) ? sanitize_text_field($_POST['context']) : 'student';

    global $wpdb, 
    $table_proqyz_v3_progress_submissions, 
    $ST_OPTION_st_proqyz__open_ai_enable,
    $ST_OPTION_st_proqyz__open_ai_apikey,
    $ST_OPTION_st_proqyz_IELTS_LMS_ai_speaking_evaluation_enable;

    $openai_enabled = (bool) get_option($ST_OPTION_st_proqyz__open_ai_enable, false);
    $openai_apikey  = get_option($ST_OPTION_st_proqyz__open_ai_apikey, '');
    $ai_speaking_enabled = (bool) get_option($ST_OPTION_st_proqyz_IELTS_LMS_ai_speaking_evaluation_enable, false);

    if (!$openai_enabled || empty($openai_apikey) || !$ai_speaking_enabled) {
        wp_send_json([
            'error' => (object) [
                'message' => 'AI Evaluation is not enabled or configured for speaking.',
            ],
        ]);
    }

    $result = $wpdb->get_row($wpdb->prepare(
        "SELECT `ID`, `user_id`
        FROM {$table_proqyz_v3_progress_submissions}
        WHERE `ID` = %d
        LIMIT 1",
        $result_id
    ));

    if (!$result) {
        wp_send_json([
            'error' => (object) [
                'message' => 'Result not found.',
            ],
        ]);
    }

    add_filter('https_ssl_verify', '__return_false');
    add_filter('https_local_ssl_verify', '__return_false');
    $response = wp_remote_post(rest_url('spacetree/proqyz/speaking/ai/evaluation'), [
        'method'  => 'POST',
        'body'    => [
            'result_id' => $result_id,
            'context'   => $context,
        ],
        'timeout' => 60,
    ]);

    if (is_wp_error($response)) {
        wp_send_json([
            'error' => [
                'message' => '[server unreachable] Failed to process AI evaluation',
                "res"     => $response
            ]
        ]);
    } else {
        $response_body = (object) json_decode($response['body']);
        if( $response_body->success ) {
            wp_send_json([
                "success" => $response_body->success
            ]);
        }

        if( $response_body->error ) {
            wp_send_json([
                "error" => $response_body->error
            ]);
        }

        wp_send_json([
            "error" => (object) [
                "message" => "invalid ajax response",
                "res"    => $response
            ]
        ]);
    }

}

/**
 * v3.1.0
 * @var proqyz-reset-evaluation
 */
add_action('wp_ajax_proqyz-reset-evaluation', 'proqyz_reset_evaluation_callback');
function proqyz_reset_evaluation_callback() {
    if (
        isset($_POST['section_id']) && isset($_POST['result_id']) &&
        !empty($_POST['section_id']) && !empty($_POST['result_id'])
    ) {
        $result_id      = sanitize_text_field($_POST['result_id']);
        $section_id     = sanitize_text_field($_POST['section_id']);

        global $wpdb, 
        $table_proqyz_v3_submissions_review, 
        $table_proqyz_v3_submissions_review_meta; 

        # match it with student_id - to ensure if student is making that request
        $get_review = $wpdb->get_row("SELECT `ID` FROM {$table_proqyz_v3_submissions_review} WHERE `result_id` = '$result_id' AND `section_id` = '$section_id' LIMIT 1");
        if( !$get_review ) {
            wp_send_json([
                'error'  => (object) [
                    "message" => ' Review not found or Already removed'
                ]
            ]);
        }

        # review id for removing meta
        $review_id = $get_review->ID;

        $meta_removed = $wpdb->delete($table_proqyz_v3_submissions_review_meta, [
            "review_id" => $review_id
        ]);


        if( !$meta_removed ) {
            wp_send_json([
                'error'  => (object) [
                    "message" => 'Failed to remove Evaluation metadata'
                ]
            ]);
        }

        $remove_review = $wpdb->delete($table_proqyz_v3_submissions_review, [
            "ID" => $review_id
        ]);

        if( !$remove_review ) {
            wp_send_json([
                'error'  => (object) [
                    "message" => 'Failed to remove Evaluation'
                ]
            ]);
        }

        wp_send_json([
            'success'  => (object) [
                "message" => 'Evaluation reset successfully'
            ]
        ]);


    } else {
        wp_send_json([
            'error' => [
                'message' => 'Missing required parameters',
            ]
        ]);
    }
}



/**
 * v2.1.0
 * status: completed
 * quiz_category: speaking
 * @var proqyz-student--submit-reevaluation-request-speaking
 * description: submit re-evaluation request from the students to the instructor
 */
add_action('wp_ajax_proqyz-student--submit-reevaluation-request-speaking', 'proqyz_submit_reevaluation_request_callback');
function proqyz_submit_reevaluation_request_callback() {
    if (
        isset($_POST['result_id']) && !empty($_POST['result_id'])
    ) {
        

        if( !isset($_POST['reason']) && empty($_POST['reason'])) {
            wp_send_json([
                'error' => [
                    'message' => 'Reason is required',
                ]
            ]);
        }

        $result_id      = sanitize_text_field($_POST['result_id']);
        $reason         = sanitize_text_field($_POST['reason']);

        global $wpdb, 
        $table_proqyz_v3_submissions_review, 
        $table_proqyz_v3_submissions_review_meta; 

        # match it with student_id - to ensure if student is making that request
        $get_review = $wpdb->get_row("SELECT `ID` FROM {$table_proqyz_v3_submissions_review} WHERE `result_id` = '$result_id' LIMIT 1");
        if( !$get_review ) {
            wp_send_json([
                'error'  => (object) [
                    "message" => ' Review not found or Already removed'
                ]
            ]);
        }

        # review id for removing meta
        $review_id = $get_review->ID;
        $review_meta_key = 're-evaluation';
        $check_meta = $wpdb->get_row("SELECT `ID` FROM {$table_proqyz_v3_submissions_review_meta} WHERE `review_id` = '$review_id' AND `meta_key` = '$review_meta_key' AND `meta_status` = 1 ");
        if( !$check_meta ) {
            $wpdb->insert($table_proqyz_v3_submissions_review_meta, [
                "review_id"     => $review_id,
                "meta_key"      => $review_meta_key,
                "meta_value"    => serialize((object) [
                    "status"    => true,
                    "reason"    => $reason
                ]),
                "meta_status"   => 1
            ]);
        } else {

            $wpdb->update($table_proqyz_v3_submissions_review_meta, [
                "meta_value"    => serialize((object) [
                    "status"    => true,
                    "reason"    => $reason
                ])
            ], [
                "ID" => $check_meta->ID,
            ]);
        }
        

        wp_send_json([
            'success'  => (object) [
                "message" => 'Your re-evaluation request has been sent successfully.'
            ]
        ]);


    } else {
        wp_send_json([
            'error' => [
                'message' => 'Missing required parameters',
            ]
        ]);
    }
}

/**
 * v2.1.0
 * status: pending
 * description: reset ai evaluation for speaking by instructor
 * quiz_category: speaking
 * @var proqyz-reset-evaluation-speaking
 */
add_action('wp_ajax_proqyz-instructor--reset-ai-evaluation-speaking', 'proqyz_reset_evaluation_speaking_callback');
function proqyz_reset_evaluation_speaking_callback() {
    if (
        isset($_POST['result_id']) && !empty($_POST['result_id'])
    ) {
        $result_id      = sanitize_text_field($_POST['result_id']);
        global $wpdb, 
        $table_proqyz_v3_submissions_review, 
        $table_proqyz_v3_submissions_review_meta; 

        # match it with student_id - to ensure if student is making that request
        $get_review = $wpdb->get_row("SELECT `ID` FROM {$table_proqyz_v3_submissions_review} WHERE `result_id` = '$result_id' LIMIT 1");
        if( !$get_review ) {
            wp_send_json([
                'error'  => (object) [
                    "message" => ' Review not found or Already removed'
                ]
            ]);
        }

        # review id for removing meta
        $review_id = $get_review->ID;

        // ai meta 1
        $wpdb->delete($table_proqyz_v3_submissions_review_meta, [
            'meta_key' => 'ai-review-content',
            "review_id" => $review_id
        ]);
        // ai meta 2
        $wpdb->delete($table_proqyz_v3_submissions_review_meta, [
            'meta_key' => 'ai-review-schema',
            "review_id" => $review_id
        ]);

        // ai meta 3
        $wpdb->update($table_proqyz_v3_submissions_review_meta, [
            'meta_value' => 'pending',
        ], [
            "review_id" => $review_id,
            "meta_key" => 'review-status',
            "meta_status" => 1
        ]);

        // ai meta 4
        $wpdb->delete($table_proqyz_v3_submissions_review_meta, [
            'meta_key' => 'prompt',
            "review_id" => $review_id
        ]);

        // ai meta 5
        $wpdb->delete($table_proqyz_v3_submissions_review_meta, [
            'meta_key' => 'response',
            "review_id" => $review_id
        ]);

        // ai meta 6
        $wpdb->delete($table_proqyz_v3_submissions_review_meta, [
            'meta_key' => 're-evaluation',
            "review_id" => $review_id
        ]);


        wp_send_json([
            'success'  => (object) [
                "message" => 'AI Evaluation reset successfully'
            ]
        ]);


    } else {
        wp_send_json([
            'error' => [
                'message' => 'Missing required parameters',
            ]
        ]);
    }
}



/**
 * v2.1.0
 * @var proqyz-remove-writing-review
 */
add_action('wp_ajax_proqyz-remove-writing-review', 'proqyz_remove_writing_review_callback');
function proqyz_remove_writing_review_callback() {
    if(isset($_POST['review_id']) && !empty($_POST['review_id'])) {
        global $wpdb, 
        $table_proqyz_v3_submissions_review, 
        $table_proqyz_v3_submissions_review_meta; 

        $review_id = $_POST['review_id'];
        # match it with student_id - to ensure if student is making that request
        $get_review = $wpdb->get_row("SELECT `ID` FROM {$table_proqyz_v3_submissions_review} WHERE `ID` = '$review_id'LIMIT 1");
        if( !$get_review ) {

            $wpdb->delete($table_proqyz_v3_submissions_review_meta, [
                "review_id" => $review_id
            ]);

            wp_send_json([
                'error'  => (object) [
                    "message" => ' Review not found or Already removed'
                ]
            ]);
        }

        $wpdb->delete($table_proqyz_v3_submissions_review, [
            "ID" => $review_id
        ]);

        $wpdb->delete($table_proqyz_v3_submissions_review_meta, [
            "review_id" => $review_id
        ]);

        wp_send_json([
            'success'  => (object) [
                "message" => 'Review removed'
            ]
        ]);



    } else {
        wp_send_json([
            'error' => [
                'message' => 'Review id is missing',
            ]
        ]);
    }
}

/**
 * v3.1.0
 * @var proqyz-get-evaluation-data-teacher
 */
add_action('wp_ajax_proqyz-get-evaluation-data-teacher', 'proqyz_get_evaluation_data_teacher_callback');
function proqyz_get_evaluation_data_teacher_callback(){
    if(!isset($_POST['result_id']) || empty($_POST['result_id'])){
        wp_send_json([
            "error" => (object) [
                "message" => "Missing Result id"
            ]
        ]);
    }

    if(!isset($_POST['section_id']) || empty($_POST['section_id'])){
        wp_send_json([
            "error" => (object) [
                "message" => "Missing Section id"
            ]
        ]);
    }



    global $wpdb,
    $table_proqyz_v3_submissions_review, 
    $table_proqyz_v3_submissions_review_meta,
    $table_proqyz_v3_progress_submissions;
    $result_id = $_POST['result_id'];
    $section_id = $_POST['section_id'];

    # get review if exists
    $review_id = null;
    $review_data = [];
    $review_content_tmp = isset($_POST['user_response'])? stripslashes($_POST['user_response']) : "";

    $get_progress = $wpdb->get_row("SELECT `ID` FROM {$table_proqyz_v3_progress_submissions} WHERE `ID` = '$result_id' AND `status` = 1 LIMIT 1");
    if( !$get_progress ) {
        wp_send_json([
            "error" => (object) [
                "message" => "Result not found"
            ]
        ]);
    }

    $get_review = $wpdb->get_row("SELECT `ID` FROM {$table_proqyz_v3_submissions_review} WHERE `result_id` = '$result_id' AND `section_id` = '$section_id' AND `status` = 1 LIMIT 1");
    if( $get_review ){
        $review_id                  = $get_review->ID;
        $review_content_meta        = $wpdb->get_row("SELECT `meta_value` FROM {$table_proqyz_v3_submissions_review_meta} WHERE `meta_key` = 'review-feedback-content' AND `review_id` = '$review_id' AND `meta_status` = 1 LIMIT 1");
        $review_scores_meta         = $wpdb->get_row("SELECT `meta_value` FROM {$table_proqyz_v3_submissions_review_meta} WHERE `meta_key` = 'review-scores' AND `review_id` = '$review_id' AND `meta_status` = 1 LIMIT 1");
        $review_comments_meta       = $wpdb->get_row("SELECT `meta_value` FROM {$table_proqyz_v3_submissions_review_meta} WHERE `meta_key` = 'review-comments' AND `review_id` = '$review_id' AND `meta_status` = 1 LIMIT 1");
        $review_comment_ids_meta    = $wpdb->get_row("SELECT `meta_value` FROM {$table_proqyz_v3_submissions_review_meta} WHERE `meta_key` = 'review-comment-ids' AND `review_id` = '$review_id' AND `meta_status` = 1 LIMIT 1");
        
        
        $review_data["review_content"] = isset($review_content_meta->meta_value)? stripslashes($review_content_meta->meta_value) : $review_content_tmp;
        $review_data["review_scores"] = isset($review_scores_meta->meta_value)? (array) json_decode($review_scores_meta->meta_value) : (array) [1,1,1,1];
        $review_data["review_comments"] = isset($review_comments_meta->meta_value)? (array) maybe_unserialize($review_comments_meta->meta_value) : [];
        $review_data["review_comment_ids"] = isset($review_comment_ids_meta->meta_value)? (array) maybe_unserialize($review_comment_ids_meta->meta_value) : [];
    } else {
        $review_data["review_content"] = $review_content_tmp;
        $review_data["review_scores"] = (array) [1,1,1,1];
        $review_data["review_comments"] = [];
        $review_data["review_comment_ids"] = [];
    }


    wp_send_json([
        "success" => (object) [
            "message" => "review_loaded",
            "data" => $review_data
        ]
    ]);


    
}


/**
 * status: pending
 * v3.1.0
 */
add_action('wp_ajax_proqyz-teacher__evaluation-form-v2', 'proqyz_teacher__evaluation_form_v2_callback');
function proqyz_teacher__evaluation_form_v2_callback(){
    if(!isset($_POST['result_id']) || empty($_POST['result_id'])){
        wp_send_json([
            "error" => (object) [
                "message" => "Missing Result id"
            ]
        ]);
    }

    if(!isset($_POST['section_id']) || empty($_POST['section_id'])){
        wp_send_json([
            "error" => (object) [
                "message" => "Missing Section id"
            ]
        ]);
    }

    if(!isset($_POST['section_order']) || empty($_POST['section_order'])){
        wp_send_json([
            "error" => (object) [
                "message" => "Missing Section order"
            ]
        ]);
    }

    global $wpdb,
    $table_proqyz_v3_submissions_review, 
    $table_proqyz_v3_submissions_review_meta,
    $table_proqyz_v3_progress_submissions, 
    $table_proqyz_v3_progress_submissions_meta,
    $table_proqyz_v3_progress_submissions_score;

    $result_id = $_POST['result_id'];
    $section_id = $_POST['section_id'];
    $section_order = $_POST['section_order'];
    $content = isset($_POST['content'])? stripslashes($_POST['content']) : '';
    $scores = isset($_POST['scores'])? (array) $_POST['scores'] : [1,1,1,1];
    $comment_ids = isset($_POST['comment_ids'])? (array) $_POST['comment_ids'] : [];
    $comments = isset($_POST['comments'])? (array) $_POST['comments'] : [];
    $reviewer_id    = get_current_user_id();

    $get_progress = $wpdb->get_row("SELECT `user_id` FROM {$table_proqyz_v3_progress_submissions} WHERE `ID` = '$result_id' AND `status` = 1 LIMIT 1");
    if( !$get_progress ) {
        wp_send_json([
            "error" => (object) [
                "message" => "Result not found"
            ]
        ]);
    }

    // get score from submissions meta
    $session_score = $wpdb->get_var("SELECT `score_data` FROM {$table_proqyz_v3_progress_submissions_score} WHERE `submission_id` = '$result_id' AND `user_id` = '$student_id' LIMIT 1");
    $session_score = (array) unserialize($session_score) || [];
    $student_id = $get_progress->user_id;
    # get review id from selected section_id
    $get_review         = $wpdb->get_row("SELECT `ID` FROM {$table_proqyz_v3_submissions_review} WHERE `result_id` = '$result_id' AND `user_id` = '$student_id' AND `status` = 1 AND `section_id` = '$section_id' LIMIT 1");
    if( !$get_review ) {
        $insert_review = $wpdb->insert($table_proqyz_v3_submissions_review, [
            "result_id"     => $result_id,
            "user_id"       => $student_id,
            "section_id"    => $section_id,
            "status"        => 1
        ]);

        if( $insert_review ) {
            $review_id = $wpdb->insert_id;
        } else {
            wp_send_json([
                "error" => (object) [
                    "message"   => "Failed to post review",
                    "res_type"  => "error",
                    "status"    => 200
                ]
            ]);
        }
    } else {
        $review_id = $get_review->ID;
    }

    # insert of update review meta
    $review_feedback_content_key = $wpdb->get_row("SELECT `meta_value`, `ID` FROM {$table_proqyz_v3_submissions_review_meta} WHERE `meta_key` = 'review-feedback-content' AND `review_id` = '$review_id' AND `meta_status` = 1 LIMIT 1");
    if( $review_feedback_content_key ) { 
        $wpdb->update($table_proqyz_v3_submissions_review_meta, [
            "meta_value"    => $wpdb->_real_escape($content),
        ], [
            "ID"            => $review_feedback_content_key->ID,
            "meta_key"      => "review-feedback-content",
            "meta_status"   => 1,
            "review_id"     => $review_id

        ]);
    } else {
        $wpdb->insert($table_proqyz_v3_submissions_review_meta, [
            "meta_value"    => $wpdb->_real_escape($content),
            "meta_key"      => "review-feedback-content",
            "meta_status"   => 1,
            "review_id"     => $review_id
        ]);
    }

    # 2.) review scores
    $review_feedback_score_key = $wpdb->get_row("SELECT `meta_value`, `ID` FROM {$table_proqyz_v3_submissions_review_meta} WHERE `meta_key` = 'review-scores' AND `review_id` = '$review_id' AND `meta_status` = 1 LIMIT 1");
    if( $review_feedback_score_key ) { 
        $wpdb->update($table_proqyz_v3_submissions_review_meta, [
            "meta_value"    => json_encode($scores),
        ], [
            "ID"            => $review_feedback_score_key->ID,
            "meta_key"      => "review-scores",
            "meta_status"   => 1,
            "review_id"     => $review_id

        ]);
    } else {
        $wpdb->insert($table_proqyz_v3_submissions_review_meta, [
            "meta_value"    => json_encode($scores),
            "meta_key"      => "review-scores",
            "meta_status"   => 1,
            "review_id"     => $review_id
        ]);
    }

    # 3.) review writter
    $review_feedback_key = $wpdb->get_row("SELECT `meta_value`, `ID` FROM {$table_proqyz_v3_submissions_review_meta} WHERE `meta_key` = 'reviewer' AND `review_id` = '$review_id' AND `meta_status` = 1 LIMIT 1");
    if( $review_feedback_key ) { 
        $wpdb->update($table_proqyz_v3_submissions_review_meta, [
            "meta_value"    => $reviewer_id,
        ], [
            "ID"            => $review_feedback_key->ID,
            "meta_key"      => "reviewer",
            "meta_status"   => 1,
            "review_id"     => $review_id

        ]);
    } else {
        $wpdb->insert($table_proqyz_v3_submissions_review_meta, [
            "review_id"     => $review_id,
            "meta_key"      => "reviewer",
            "meta_value"    => $reviewer_id,
            "meta_status"   => 1
        ]);
    }

    # 4.) review-comments
    $review_comments_key = $wpdb->get_row("SELECT `meta_value`, `ID` FROM {$table_proqyz_v3_submissions_review_meta} WHERE `meta_key` = 'review-comments' AND `review_id` = '$review_id' AND `meta_status` = 1 LIMIT 1");
    if( $review_comments_key ) { 
        $wpdb->update($table_proqyz_v3_submissions_review_meta, [
            "meta_value"    => serialize($comments),
        ], [
            "ID"            => $review_comments_key->ID,
            "meta_key"      => "review-comments",
            "meta_status"   => 1,
            "review_id"     => $review_id

        ]);
    } else {
        $wpdb->insert($table_proqyz_v3_submissions_review_meta, [
            "review_id"     => $review_id,
            "meta_key"      => "review-comments",
            "meta_value"    => serialize($comments),
            "meta_status"   => 1
        ]);
    }

    # 4.) review-comment-ids
    $review_comment_ids_key = $wpdb->get_row("SELECT `meta_value`, `ID` FROM {$table_proqyz_v3_submissions_review_meta} WHERE `meta_key` = 'review-comment-ids' AND `review_id` = '$review_id' AND `meta_status` = 1 LIMIT 1");
    if( $review_comment_ids_key ) { 
        $wpdb->update($table_proqyz_v3_submissions_review_meta, [
            "meta_value"    => serialize($comment_ids),
        ], [
            "ID"            => $review_comment_ids_key->ID,
            "meta_key"      => "review-comment-ids",
            "meta_status"   => 1,
            "review_id"     => $review_id

        ]);
    } else {
        $wpdb->insert($table_proqyz_v3_submissions_review_meta, [
            "review_id"     => $review_id,
            "meta_key"      => "review-comment-ids",
            "meta_value"    => serialize($comment_ids),
            "meta_status"   => 1
        ]);
    }

    $session_score["task-".$section_order] = (array) $scores;
    # mark as reviewed and email if possible

    // update score meta in submission meta table
    // maybe this is not exists so insert/update method is needed 
    proqyz_utils_submissions_score_v3($result_id, $student_id, serialize($session_score));

    $wpdb->update($table_proqyz_v3_progress_submissions, [
        'review'    => 1,
        'date_modified' => date("U")
    ], ['ID' => $result_id]);

    # email logic
    apply_filters('proqyz_quiz__on_evaluation_writing', [
        "user_id"               => $student_id,
        "reviewer_id"           => $reviewer_id,
        "result_id"             => $result_id
    ]);

    wp_send_json([
        "success" => (object) [
            "message" => "Review posted successfully",
            "reload"  => $get_review? false : true  
        ]
    ]);
}

/**
 * action: speaking-ajax--set-primary-evaluation
 * v2.1.0
 */
add_action('wp_ajax_speaking-ajax--set-primary-evaluation', 'speaking_ajax_set_primary_evaluation_callback');
function speaking_ajax_set_primary_evaluation_callback(){
    global $wpdb, $table_proqyz_v3_submissions_review, $table_proqyz_v3_submissions_review_meta;
    $result_id = $_POST['result_id'];
    $primary = $_POST['primary'];
    // get review id using result id 
    $review_id = $wpdb->get_row("SELECT `ID` FROM {$table_proqyz_v3_submissions_review} WHERE `result_id` = '$result_id' AND `status` = 1 LIMIT 1");
    if( $review_id ) {
        $review_id = $review_id->ID;
        $wpdb->update($table_proqyz_v3_submissions_review_meta, [
            "meta_value"    => $primary,
        ], [
            "meta_key"      => "reviewer",
            "meta_status"   => 1,
            "review_id"     => $review_id

        ]);
        wp_send_json([
            "success" => (object) [
                "message" => "Primary evaluation set successfully"
            ]
        ]);
    } else {
        wp_send_json([
            "error" => (object) [
                "message" => "Review not found",
                "res" => $review_id,
                "result_id" => $result_id
            ]
        ]);
    }
}

