# from flask import Blueprint, request, jsonify
# from mongoengine import DoesNotExist
# from datetime import datetime
# import json

# from models.mcq_result import MCQResult
# from models.quiz_share import QuizShare
# from models.image import Image
# from models.mcq import MCQ
# from models.user import User  # Needed for ReferenceField lookups

# savemcq_bp = Blueprint("savemcq_bp", __name__)

# @savemcq_bp.route("/save-mcq", methods=["POST"])
# def save_mcq():
#     # Only POST allowed
#     if request.method != "POST":
#         return jsonify({"status": False, "message": "Unauthorized method."}), 401

#     # Try to read JSON payload first
#     if request.is_json:
#         data = request.get_json(silent=True) or {}
#     else:
#         # Handle form-data / multipart form
#         data = request.form.to_dict()

#         # If mcq_data is sent as a JSON string inside form-data
#         if "mcq_data" in data:
#             try:
#                 data["mcq_data"] = json.loads(data["mcq_data"])
#             except json.JSONDecodeError:
#                 return jsonify({"status": False, "message": "Invalid mcq_data format"}), 400

#     # Extract fields
#     user_id = data.get("user_id")
#     output_file = data.get("output_file")
#     mcq_data = data.get("mcq_data")

#     # Validate
#     if not user_id:
#         return jsonify({"status": False, "message": "Enter user id"}), 400
#     if not output_file:
#         return jsonify({"status": False, "message": "Enter file path"}), 400
#     if not isinstance(mcq_data, list):
#         return jsonify({"status": False, "message": "mcq_data must be a list"}), 400

#     try:
#         user_ref = User.objects.get(id=user_id)
#     except DoesNotExist:
#         return jsonify({"status": False, "message": "User not found"}), 404

#     # Get quiz questions
#     questions = list(MCQ.objects(output_file=output_file))
#     total_questions = len(mcq_data)
#     skipped_answers = 0
#     correct_answers = 0
#     wrong_answers = 0

#     # Get single image
#     image_doc = Image.objects(output_file=output_file).first()
#     if not image_doc:
#         return jsonify({"status": False, "message": "Quiz not found"}), 404

#     # Check if shared quiz
#     is_shared_quiz = False
#     quiz_shared_by = None
#     shared_quiz_data = QuizShare.objects(
#         quiz_id=str(image_doc.id),
#         user_id=user_ref
#     ).first()
#     if shared_quiz_data:
#         is_shared_quiz = True
#         quiz_shared_by = shared_quiz_data.shared_by

#     # Compare user answers
#     for user_q in mcq_data:
#         db_q = next((q for q in questions if q.question == user_q.get("question")), None)
#         if db_q:
#             selected_answer = user_q.get("selected_answer")
#             correct_answer = db_q.correct_answer
#             if not selected_answer:
#                 skipped_answers += 1
#             elif selected_answer == correct_answer:
#                 correct_answers += 1
#             else:
#                 wrong_answers += 1

#     correct_answer_score = 1
#     total_score = correct_answers * correct_answer_score
#     user_position = None

#     # Calculate rank for shared quizzes
#     if is_shared_quiz:
#         all_attempts = MCQResult.objects(
#             quiz_id=str(image_doc.id),
#             is_shared_quiz=1
#         ).order_by("-score", "created_date")

#         higher_scores = 0
#         same_scores_earlier = 0
#         for attempt in all_attempts:
#             if attempt.score > total_score:
#                 higher_scores += 1
#             elif attempt.score == total_score and attempt.created_date < datetime.utcnow():
#                 same_scores_earlier += 1

#         user_position = higher_scores + same_scores_earlier + 1

#     # Save MCQ result
#     mcq_result = MCQResult(
#         user_id=user_ref,
#         output_file=output_file,
#         quiz_id=str(image_doc.id),
#         total_questions=total_questions,
#         skipped_answers=skipped_answers,
#         correct_answers=correct_answers,
#         wrong_answers=wrong_answers,
#         score=total_score,
#         rank=user_position,
#         is_shared_quiz=1 if is_shared_quiz else 0,
#         mcq_data=json.dumps(mcq_data),
#         shared_by=quiz_shared_by
#     )
#     mcq_result.save()

#     # Map user answers for updating extracted_mcq & other_extracted_mcq
#     extracted_mcq = json.loads(image_doc.extracted_mcq or "[]")
#     other_extracted_mcq = json.loads(image_doc.other_extracted_mcq or "[]")
#     user_answers_map = {
#         f"Question: {q.get('question').strip()}": q.get("selected_answer")
#         for q in mcq_data
#     }

#     # Update plain text MCQs
#     for i, line in enumerate(extracted_mcq):
#         if str(line).startswith("Question:"):
#             selected_answer = user_answers_map.get(line.strip())
#             if selected_answer:
#                 extracted_mcq[i] += f"\nUser Selected Answer: {selected_answer}"

#     # Update structured JSON MCQs
#     for item in other_extracted_mcq:
#         q_text = item.get("question", "").strip()
#         selected_answer = user_answers_map.get(q_text)
#         item["User Selected Answer"] = selected_answer if selected_answer else "Skipped"

#     return jsonify({
#         "status": True,
#         "message": "MCQ data saved successfully",
#         "data": {
#             "total_questions": total_questions,
#             "skipped_answers": skipped_answers,
#             "correct_answers": correct_answers,
#             "wrong_answers": wrong_answers + skipped_answers,
#             "score": total_score,
#             "rank": user_position,
#             "output": extracted_mcq,
#             "array_output": other_extracted_mcq
#         }
#     }), 200 


from flask import Blueprint, request, jsonify
from mongoengine import DoesNotExist
from datetime import datetime
import json

from models.mcq_result import MCQResult
from models.quiz_share import QuizShare
from models.image import Image
from models.mcq import MCQ
from models.user import User  # ReferenceField target
from utils.jwt_service import jwt_required

savemcq_bp = Blueprint("savemcq_bp", __name__)

@savemcq_bp.route("/save-mcq", methods=["POST"])
@jwt_required
def save_mcq():
    # keep parity with PHP
    user_id = getattr(request, "user_id", None)
    if request.method != "POST":
        return jsonify({"status": False, "message": "Unauthorized method."}), 401

    # accept JSON and form-data (like PHP's getVar)
    if request.is_json:
        payload = request.get_json(silent=True) or {}
        # user_id = payload.get("user_id")
        user_id= user_id or payload.get("user_id")  # fallback if not from token
        output_file = payload.get("output_file")
        mcq_data = payload.get("mcq_data")
    else:
        # user_id = request.form.get("user_id")
        user_id = user_id or request.form.get("user_id")  # fallback if not from token
        output_file = request.form.get("output_file")
        mcq_data = request.form.get("mcq_data")
        if isinstance(mcq_data, str):
            try:
                mcq_data = json.loads(mcq_data)
            except json.JSONDecodeError:
                return jsonify({"status": False, "message": "Invalid mcq_data format"}), 400

    # required fields (as in PHP)
    if not user_id:
        return jsonify({"status": False, "message": "Enter user id"}), 400
    if not output_file:
        return jsonify({"status": False, "message": "Enter file path"}), 400
    if not isinstance(mcq_data, list):
        return jsonify({"status": False, "message": "mcq_data must be a list"}), 400

    # user reference (model has ReferenceField)
    try:
        user_ref = User.objects.get(id=user_id)
    except DoesNotExist:
        return jsonify({"status": False, "message": "User not found"}), 404

    # quiz/image by output_file
    image_doc = Image.objects(output_file=output_file).first()
    if not image_doc:
        return jsonify({"status": False, "message": "Quiz not found"}), 404

    # all MCQs for this output_file
    questions = list(MCQ.objects(output_file=output_file))

    total_questions = len(mcq_data)
    skipped_answers = 0
    correct_answers = 0
    wrong_answers = 0

    # shared quiz check — NOTE: your model uses ReferenceFields
    # PHP filters by raw ids; here we use references exactly
    shared_quiz_data = QuizShare.objects(
        quiz_id=image_doc,
        user_id=user_ref
    ).first()

    is_shared_quiz = bool(shared_quiz_data)
    quiz_shared_by = shared_quiz_data.shared_by_user_id if shared_quiz_data else None

    # evaluate answers (exact question string match, like PHP)
    for uq in mcq_data:
        # tolerate dicts only (mirrors your Flask version)
        q_text = (uq.get("question") if isinstance(uq, dict) else None) or ""
        sel = (uq.get("selected_answer") if isinstance(uq, dict) else None)

        db_q = next((q for q in questions if q.question == q_text), None)
        if not db_q:
            continue

        if not sel:
            skipped_answers += 1
        elif sel == db_q.correct_answer:
            correct_answers += 1
        else:
            wrong_answers += 1

    correct_answer_score = 1
    total_score = correct_answers * correct_answer_score
    user_position = None

    # rank calculation — mirror PHP behavior
    if is_shared_quiz:
        all_attempts = MCQResult.objects(
            quiz_id=str(image_doc.id),  # your MCQResult.quiz_id is a StringField
            is_shared_quiz=1
        ).order_by("-score", "created_date")

        higher_scores = 0
        same_scores_earlier = 0
        now = datetime.utcnow()
        for attempt in all_attempts:
            if attempt.score and attempt.score > total_score:
                higher_scores += 1
            elif attempt.score == total_score and attempt.created_date and attempt.created_date < now:
                same_scores_earlier += 1

        user_position = higher_scores + same_scores_earlier + 1

    # save MCQResult (field names exactly as in your model)
    mcq_result = MCQResult(
        user_id=user_ref,
        output_file=output_file,
        quiz_id=str(image_doc.id),       # StringField in MCQResult
        total_questions=total_questions,
        skipped_answers=skipped_answers,
        correct_answers=correct_answers,
        wrong_answers=wrong_answers,
        score=total_score,
        rank=user_position,
        is_shared_quiz=1 if is_shared_quiz else 0,
        mcq_data=json.dumps(mcq_data),   # model stores JSON as string
        shared_by=quiz_shared_by         # ReferenceField(User)
        # created_date defaulted by model
    )
    mcq_result.save()

    # Build the user answers map like PHP: key = "Question: <trimmed>"
    user_answers_map = {}
    for uq in mcq_data:
        q_text = (uq.get("question") if isinstance(uq, dict) else None) or ""
        sel = (uq.get("selected_answer") if isinstance(uq, dict) else None)
        user_answers_map["Question: " + q_text.strip()] = sel if sel else None

    # Read Image.extracted_mcq / other_extracted_mcq (DictField); support also string JSON for safety
    def _ensure_json_struct(val):
        if val is None:
            return []
        if isinstance(val, (list, dict)):
            return val
        if isinstance(val, str):
            try:
                return json.loads(val)
            except Exception:
                return []
        return []

    extracted_mcq_val = _ensure_json_struct(image_doc.extracted_mcq)
    other_extracted_mcq_val = _ensure_json_struct(image_doc.other_extracted_mcq)

    # We expect plain-text list for extracted_mcq, and list of dicts for other_extracted_mcq,
    # but keep robust to either being dict.
    extracted_list = extracted_mcq_val if isinstance(extracted_mcq_val, list) else []
    other_list = other_extracted_mcq_val if isinstance(other_extracted_mcq_val, list) else []

    # Update extracted_mcq (plain text)
    updated_extracted = []
    for line in extracted_list:
        if isinstance(line, str) and line.startswith("Question:"):
            question_text = line.strip()
            selected_answer = user_answers_map.get(question_text)
            if selected_answer:
                line = f"{line}\nUser Selected Answer: {selected_answer}"
        updated_extracted.append(line)

    # Update other_extracted_mcq (structured JSON) — NOTE:
    # PHP looks up without the "Question: " prefix, leaving a mismatch by design.
    updated_other = []
    for item in other_list:
        if isinstance(item, dict):
            q_text = (item.get("question") or "").strip()
            sel = user_answers_map.get(q_text)  # (kept mismatch to mirror PHP)
            item["User Selected Answer"] = sel if sel else "Skipped"
        updated_other.append(item)

    # Response mirrors PHP (wrong_answers includes skipped in the returned number)
    return jsonify({
        "status": True,
        "message": "MCQ data saved successfully",
        "data": {
            "total_questions": total_questions,
            "skipped_answers": skipped_answers,
            "correct_answers": correct_answers,
            "wrong_answers": wrong_answers + skipped_answers,  # parity with PHP
            "score": correct_answers * correct_answer_score,
            "rank": user_position,
            "output": updated_extracted,
            "array_output": updated_other
        }
    }), 200
