<?php
namespace QuizPress\Ajax;


if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

use QuizPress\Classes\AbstractAjaxHandler;
use QuizPress\Classes\Sanitizer;
use QuizPress\API\Query\Attempts as Query;
use QuizPress\API\Query\Questions as Questions;
use QuizPress\API\Query\Answers as Answers;

class Frontend extends AbstractAjaxHandler{
    protected $namespace = 'quizpress/frontend';
    public function __construct()
    {
        $this->actions = [
			'get_quiz_questions_for_attempt' => array(
				'callback' => array( $this, 'get_quiz_questions_for_attempt' ),
				'capability' => 'read',
			),
			'insert_quiz_answer' => array(
				'callback' => array( $this, 'insert_quiz_answer' ),
				'capability' => 'read',
			),
			'get_user_attempt_answer_details' => array(
				'callback' => array( $this, 'get_user_attempt_answer_details' ),
				'capability' => 'read'
			),
			'get_user_attempt_by_quiz' => array(
				'callback' => array( $this, 'get_user_attempt_by_quiz' ),
				'capability' => 'read',
			),
			'get_user_attempt_feedback' => array(
				'callback' => array( $this, 'get_user_attempt_feedback' ),
				'capability' => 'read',
			),
		];
    }

	public function get_quiz_questions_for_attempt($payload_data) {
		$payload = Sanitizer::sanitize_payload([
			'quiz_id' => 'integer',
		], $payload_data);

		$quiz_id = $payload['quiz_id'] ?? 0;

		$questions = get_post_meta($quiz_id, 'quizpress_quiz_questions', true);
		$question_limit = (int) get_post_meta($quiz_id, 'quizpress_quiz_max_questions_for_answer', true);
		$question_ids = array_column((array) $questions, 'id');

		
		if (!empty($question_ids)) {
			// If limit is 0 or unset, randomize the full question set
			if (empty($question_limit) || $question_limit === 0) {
				$question_limit = count($question_ids);
			}
			shuffle($question_ids);
			// Limit questions to the specified number
			$limit = min($question_limit, count($question_ids));
			$random_keys = (array) array_rand($question_ids, $limit);
			$question_ids = array_intersect_key($question_ids, array_flip($random_keys));
		}

		// Get questions data in a single query
		$questions_data = Questions::get_questions_by_ids($question_ids, true);

		foreach ($questions_data as &$question_data) {
			$question_data->question_settings = json_decode($question_data->question_settings, true);
			$question_data->answers = Answers::get_question_answers_by_question_id($question_data->question_id);
			if ( $question_data->question_settings['random_answer'] ) {
				shuffle( $question_data->answers );
			}

			foreach ($question_data->answers as &$answer) {
				$answer = \QuizPress\API\Controller\Answers::prepare_answer_for_response($answer);
			}
		}
		unset($question_data); // break reference

		wp_send_json_success([
			'render_question_ids' => $question_ids,
			'questions' => $questions_data,
		]);
	}


	public function insert_quiz_answer($payload_data){
		$payload = Sanitizer::sanitize_payload([
			'quiz_id' => 'integer',
			'question_id' => 'integer',
			'attempt_id' => 'integer',
			'given_answers' => 'json',
		], $payload_data );
		
		$quiz_id = $payload['quiz_id'];
		$attempt_id = $payload['attempt_id'];
		$given_answers = $payload['given_answers'];
		$question_id = (int) $payload['question_id'];
		$question = Questions::get_question_details_by_question_id( $question_id );
		$user_id   = (int) get_current_user_id();

		if(is_array( $given_answers ) && count( $given_answers )){
			$results = [];
			foreach ( $given_answers as $given_answer ) {

				$question_score = (float) $question->question_score;
				$question_type = (string) $question->question_type;
				$answer_id = $given_answer['answer_id'] ?? '';
				$given_answer = $given_answer['answer']; 

				$negative_score = 0;
				$negative_mark = floatval( $question->question_negative_score);
				if ( ! empty( $given_answer ) && $negative_mark > 0 && empty( $correct_answer ) ) {
					$negative_score -= $negative_mark;
				}
				
				$correct_answer = 0;
				switch ( $question_type ) {

					case 'single_choice_horizontal':
					case 'single_choice':
					case 'drop_down':
					case 'true_false':
						$IDs = wp_list_pluck($given_answers, 'answer_id');
						$correct_answer = (int) Questions::is_quiz_correct_answer( $IDs, $question_id );
						break;
					case 'multiple_choice_horizontal':
					case 'multiple_choice':
						// $question_score =  Question Mark / Total Correct Answer
						$question_score = ( $question_score / Answers::get_quiz_total_correct_answer_by_question_id( $question->question_id ) );
						$IDs = wp_list_pluck($given_answers, 'answer_id');
						$correct_answer = (int) Questions::is_quiz_correct_answer( $IDs, $question_id );
						break;
					case 'fill_in_the_blanks':
						$decoded_answers = json_decode( stripslashes( $given_answer ), true );
						$given_answer_arr = wp_list_pluck( $decoded_answers, 'value' );
						$correct_answer   = (int) Answers::is_fill_in_the_blanks_quiz_correct_answer( $given_answer_arr, $question_id );
						break;

					case 'short_answer':
					case 'paragraph':
					case 'number':
					case 'date':
					case 'file_upload':
						// Example: handle short answer manually (no check yet)
						$correct_answer = 0;
						break;

					default:
						$IDs = wp_list_pluck($given_answers, 'answer_id');
						// Fallback for any other question types
						$correct_answer = (int) Answers::is_quiz_correct_answer( $IDs, $question_id );
						break;
				}
				
				$results[] = Query::quiz_attempt_answer_insert(array(
					'user_id'           => $user_id,
					'quiz_id'           => $quiz_id,
					'question_id'       => $question_id,
					'attempt_id'        => $attempt_id,
					'answer_id'         => $answer_id,
					'answer'            => $given_answer,
					'question_mark'     => $question_score,
					'achieved_mark'     => $correct_answer ? $question_score : ( $negative_score ?? '' ),
					'minus_mark'        => '',
					'is_correct'        => $correct_answer,
				));
			}
			wp_send_json_success($results);
		}
		wp_send_json_error(__('Sorry, something went wrong'));
	}

	public function get_user_attempt_answer_details( $payload_data ) {
		$payload = Sanitizer::sanitize_payload([
			'user_id' => 'integer',
			'attempt_id' => 'integer',
		], $payload_data );

		if(! $payload['user_id'] || ! $payload['attempt_id']) {
			wp_send_json_error(__('Required payload missing.'));
		}

		$attempt_id = $payload['attempt_id'];
		$user_id = ( isset( $payload['user_id'] ) ? $payload['user_id'] : 0 );

		$prepare_response = [];
		$attempt_details = Query::get_quiz_attempt_details( $attempt_id, $user_id );		
		$is_required_manual_review = false;
		foreach ( $attempt_details as $attempt_item ) {
			if ( ! $attempt_item->is_manually_reviewed ) {
				$is_required_manual_review = in_array( $attempt_item->question_type, [ 'short_answer', 'paragraph', 'number', 'date', 'file_upload' ] ) ? true : false;
			}			
			$attempt_item->is_required_manual_review = $is_required_manual_review;
			$attempt_item->given_answer = Answers::prepare_given_answer( $attempt_item->question_type, $attempt_item );
			$attempt_item->is_correct = (int) $attempt_item->is_correct;
			$attempt_item->correct_answer = Answers::prepare_correct_answer( $attempt_item->question_type, $attempt_item );
			$attempt_item->question_title = html_entity_decode( $attempt_item->question_title );
			$prepare_response[ $attempt_item->attempt_answer_id ] = $attempt_item;
		}
		wp_send_json_success( array_values( $prepare_response ) );		
	}

	public function get_user_attempt_by_quiz( $payload_data ) {
		$payload = Sanitizer::sanitize_payload( [
			'quiz_id' => 'integer'
		], $payload_data );
		$quiz_id = $payload['quiz_id'] ?? 0;
		$user_id = get_current_user_id();
		$all_attempts = \QuizPress\API\Query\Attempts::get_attempts_by_quiz_and_user_id( $quiz_id, $user_id );
		foreach ( $all_attempts as &$attempt ) {
			$info = json_decode( $attempt->attempt_info, true );
			$question_ids = isset( $info[0]['render_question_ids'] ) ? $info[0]['render_question_ids'] : $info['render_question_ids'];
			$attempt->skip_questions = Query::get_skipped_question_count( count( $question_ids ), $attempt->attempt_id );
			$attempt->attempt_info = $info;
		}
		unset( $attempt );
		$last_attempt_status = \QuizPress\API\Query\Attempts::get_last_quiz_attempt_status( $quiz_id, $user_id );
		$data = (object) [
			'status' => $last_attempt_status,
			'attempts' => $all_attempts
		];
		do_action( 'quizpress/get_attempt_status', $last_attempt_status, $quiz_id, $user_id );
		wp_send_json_success( $data );
	}
	
	public function get_user_attempt_feedback( $payload_data ) {
		$payload = Sanitizer::sanitize_payload([
			'attempt_id' => 'integer',
		], $payload_data );

		$attempt_id = ( isset( $payload['attempt_id'] ) ? $payload['attempt_id'] : 0 );

		$attempt = (object) Query::get_quiz_attempt( $attempt_id );
		$attempt->attempt_info = json_decode($attempt->attempt_info);
		$feedback = $attempt->attempt_info->feedback ?? '';

		wp_send_json_success( $feedback );
	}
}