from models.mock_test_model import *
from bson import ObjectId
from flask import request, jsonify, Blueprint
from utils.jwt_service import jwt_required
from utils.evaluater import evaluate_descriptive_answer
from models.course import Course
from models.user_course_purchase_history import UserCoursePurchase
from datetime import datetime

mock_test_bp = Blueprint("mock_test", __name__)

@mock_test_bp.route('/get_mock_tests_list', methods=['POST'])
@jwt_required
def get_mock_tests_list():
    try:
        # Get user_id from JWT (assuming jwt_required sets request.user)
        user_id = getattr(request, "user_id", None)
        if not user_id:
            return jsonify({"status": False, "message": "Invalid user id"}), 401
        course_id = request.json.get("course_id")
        if not course_id or not user_id:
            return jsonify({"status": False, "message": "course_id and user_id are required"}), 400

        # Fetch course details from MetaData as per user_id
        course_details= Course.objects(id=ObjectId(course_id), status=1).first()
        is_purchased = 0
        is_expired = 0
        if user_id:
            purchase = UserCoursePurchase.objects(
                user_id=ObjectId(user_id),
                course_id=course_details.id,
                status=1
            ).first()
            if purchase:
                is_purchased = 1
                # Example expiry logic: course expires after 365 days
                expiry_days = course_details.duration
                if purchase.purchase_date and (datetime.utcnow() - purchase.purchase_date).days > expiry_days:
                    is_expired = 1

        # Only allow access if purchased and not expired
        if not is_purchased:
            return jsonify({"status": False, "message": "Course not purchased"}), 403
        if is_expired:
            return jsonify({"status": False, "message": "Course access has expired"}), 403
        
        mock_tests = MockTest.objects(course_id=ObjectId(course_id), status=1)
        result = [{
            "mock_test_id": str(test.id),
            "title": test.title,
            "duration": test.duration,
            "total_questions": test.total_questions,
            "total_marks": test.total_marks
        } for test in mock_tests]

        return jsonify({
            "status": True,
            "is_purchased": is_purchased,
            "is_expired": is_expired,
            "data": result
        }), 200

    except Exception as e:
        return jsonify({"status": False, "message": str(e)}), 500

@mock_test_bp.route('/get_instruction', methods=['POST'])
@jwt_required
def get_instruction():
    try:
        mock_test_id = request.json.get("mock_test_id")
        if not ObjectId.is_valid(mock_test_id):
            return jsonify({"status": False, "message": "Invalid mock test ID"}), 400
        
        data= MockTest.objects(id=ObjectId(mock_test_id)).first()
        if not data:
            return jsonify({"status": False, "message": "Mock test not found"}), 404

        exam_id = data.exam.id 
        instructions_data = data.instructions

        if not instructions_data:
            return jsonify({"status": False, "message": "No instructions found for this mock test"}), 404
        exam_data= Exam.objects(id=ObjectId(exam_id)).first()
        if not exam_data:
            return jsonify({"status": False, "message": "Exam not found"}), 404
        

        return jsonify({
            "status": True,
            "data": {
                "instructions": instructions_data,
                "exam_title": exam_data.exam_title,
                "exam_description": exam_data.exam_description or "",
                "exam_icon": exam_data.icon or "",
                "mock_test_title": data.title,
                "mock_test_duration": data.duration,
                "mock_test_total_questions": data.total_questions,
                "mock_test_total_marks": data.total_marks
            }
        }), 200

    except Exception as e:
        return jsonify({"status": False, "message": str(e)}), 500

@mock_test_bp.route('/get_mock_test_questions', methods=['POST'])
@jwt_required
def get_mock_test_questions():
    try:
        mock_test_id = request.json.get("mock_test_id")
        if not ObjectId.is_valid(mock_test_id):
            return jsonify({"status": False, "message": "Invalid mock test ID"}), 400
        
        questions = MockTestQuestion.objects(mock_test=ObjectId(mock_test_id))

        result={}
        for q in questions:
            if q.question_type not in result:
                result[q.question_type]=[
                    {
                        "question_id": str(q.id),
                        "question": q.question,
                        "options": q.options,
                        "answer": q.answer,
                        "marks": q.marks
                    }
                ]
            else:
                result[q.question_type].append({
                    "question_id": str(q.id),
                    "question": q.question,
                    "options": q.options,
                    "answer": q.answer,
                    "marks": q.marks
                })


        return jsonify({"status": True, "data": result}), 200

    except Exception as e:
        return jsonify({"status": False, "message": str(e)}), 500

@mock_test_bp.route('/submit_test', methods=['POST'])
@jwt_required
def submit_test():
    try:
        mock_test_id = request.json.get("mock_test_id")
        if not ObjectId.is_valid(mock_test_id):
            return jsonify({"status": False, "message": "Invalid mock test ID"}), 400
        submitted_answers = request.json.get("data")
        
        # Fetch questions of this mock test
        questions = MockTestQuestion.objects(mock_test=ObjectId(mock_test_id))
        question_map = {str(q.id): q for q in questions}

        user_marks = 0
        result= []

        for answer in submitted_answers:
            question_id = answer.get("question_id")
            if not ObjectId.is_valid(question_id) or question_id not in question_map:
                return jsonify({"status": False, "message": f"Invalid question ID: {question_id}"}), 400
            if answer.get("question_type") in ["descriptive", "Essay"]:
                user_answer = answer.get("answer", "")
                correct_answer = question_map[question_id].answer
                similarity_score = evaluate_descriptive_answer(user_answer, correct_answer)
                if similarity_score >= 0.7:
                    marks+= question_map[question_id].marks
                    result.append({
                        "question_id": question_id,
                        "question": question_map[question_id].question,
                        "user_answer": user_answer,
                        "correct_answer": correct_answer,
                        "status": "correct",
                    })
                else:
                    result.append({
                        "question_id": question_id,
                        "question": question_map[question_id].question,
                        "user_answer": user_answer,
                        "correct_answer": correct_answer,
                        "status": "incorrect",
                    })
            else:
                user_answer = answer.get("answer", "")
                correct_answer = question_map[question_id].answer
                if user_answer == correct_answer:
                    user_marks += question_map[question_id].marks
                    result.append({
                        "question_id": question_id,
                        "question": question_map[question_id].question,
                        "user_answer": user_answer,
                        "correct_answer": correct_answer,
                        "status": "correct",
                    })
                else:
                    result.append({
                        "question_id": question_id,
                        "question": question_map[question_id].question,
                        "user_answer": user_answer,
                        "correct_answer": correct_answer,
                        "status": "incorrect",
                    })
        

        # Here you would typically save the answers to the database
        # For now, we will just return them as a confirmation
        return jsonify({
            "status": True,
            "message": "Test submitted and checked successfully",
            "marks": user_marks,
            "result": result
        }), 200

    except Exception as e:
        return jsonify({"status": False, "message": str(e)}), 500

