import tkinter as tk
from tkinter import messagebox
import requests
import random

# URL endpoints
QUESTIONS_URL = "http://143.198.172.132/rorakake/forums/get_questions.php"
SUBMIT_URL = "http://143.198.172.132/rorakake/forums/submit.php"

class RorakakeTestApp(tk.Tk):
    def __init__(self):
        super().__init__()
        # Full screen window
        self.attributes("-fullscreen", True)
        self.title("Rorakake Proficiency Test")
        
        # Data holders
        self.username = ""
        self.questions = []  # List of dictionaries with keys "question_text" and "answer_text"
        self.answer_vars = {}  # Stores a tk.StringVar for each question
        
        # Start with the login frame
        self.show_login_frame()

    def show_login_frame(self):
        self.login_frame = tk.Frame(self)
        self.login_frame.pack(expand=True)

        tk.Label(self.login_frame, text="Enter your username:", font=("Arial", 24)).pack(pady=20)
        self.username_entry = tk.Entry(self.login_frame, font=("Arial", 24))
        self.username_entry.pack(pady=10)
        tk.Button(self.login_frame, text="Start Test", font=("Arial", 24), command=self.start_test).pack(pady=20)

    def start_test(self):
        self.username = self.username_entry.get().strip()
        if not self.username:
            messagebox.showerror("Error", "Please enter a username.")
            return
        self.login_frame.destroy()
        self.fetch_questions()

    def fetch_questions(self):
        try:
            response = requests.get(QUESTIONS_URL, timeout=10)
            response.raise_for_status()
            self.questions = response.json()
        except Exception as e:
            messagebox.showerror("Error", f"Failed to load questions:\n{e}")
            self.destroy()
            return

        if len(self.questions) < 4:
            messagebox.showerror("Error", "Not enough questions to create multiple-choice options.")
            self.destroy()
            return

        self.show_test_interface()

    def show_test_interface(self):
        # Use a horizontal PanedWindow to separate questions and side info.
        paned = tk.PanedWindow(self, orient=tk.HORIZONTAL)
        paned.pack(fill="both", expand=True)

        # Left Frame: Scrollable question area.
        left_frame = tk.Frame(paned)
        paned.add(left_frame, stretch="always")

        # Create a canvas for scrolling
        canvas = tk.Canvas(left_frame)
        scrollbar = tk.Scrollbar(left_frame, orient="vertical", command=canvas.yview)
        scrollable_frame = tk.Frame(canvas)

        scrollable_frame.bind(
            "<Configure>",
            lambda e: canvas.configure(scrollregion=canvas.bbox("all"))
        )
        canvas.create_window((0, 0), window=scrollable_frame, anchor="nw")
        canvas.configure(yscrollcommand=scrollbar.set)
        canvas.pack(side="left", fill="both", expand=True)
        scrollbar.pack(side="right", fill="y")

        # Prepare list of all possible answers
        all_answers = [q["answer_text"] for q in self.questions]

        # For each question, build the multiple-choice interface.
        self.answer_vars = {}
        for idx, question in enumerate(self.questions):
            q_frame = tk.LabelFrame(scrollable_frame, text=f"Question {idx+1}", font=("Arial", 16), padx=10, pady=10)
            q_frame.pack(fill="x", padx=20, pady=10)

            # Display question text
            q_text = question.get("question_text", "No question provided")
            tk.Label(q_frame, text=q_text, font=("Arial", 14), wraplength=800, justify="left").pack(anchor="w", pady=5)
            
            # The correct answer
            correct_answer = question.get("answer_text", "")
            
            # Select 3 distractors from all answers, excluding the correct one
            distractors = [ans for ans in all_answers if ans != correct_answer]
            distractors = random.sample(distractors, 3)
            
            # Combine and shuffle the options so the correct answer is randomly placed
            options = distractors + [correct_answer]
            random.shuffle(options)
            
            # Create a StringVar for this question to store the user's selection
            var = tk.StringVar(value="")  # Default is empty (no selection)
            self.answer_vars[idx] = var
            
            # Create radio buttons for each option
            for opt in options:
                tk.Radiobutton(q_frame, text=opt, variable=var, value=opt, font=("Arial", 12)).pack(anchor="w")
        
        # Add a submit button at the bottom of the questions
        tk.Button(scrollable_frame, text="Submit Test", font=("Arial", 24), command=self.submit_test).pack(pady=20)

        # Right Frame: Side info panel.
        right_frame = tk.Frame(paned, width=300, bg="#f0f0f0")
        paned.add(right_frame)

        info_title = tk.Label(right_frame, text="Test Information", font=("Arial", 20), bg="#f0f0f0")
        info_title.pack(pady=10)
        instructions = (
            "Instructions:\n"
            "1. Select one answer per question.\n"
            "2. The test is scored out of 1000.\n"
            "3. Each question is worth an equal share of the total score.\n\n"
            "Total Questions: {}\n"
            "Points per Question: {:.2f}"
        ).format(len(self.questions), 1000 / len(self.questions))
        tk.Label(right_frame, text=instructions, font=("Arial", 14), justify="left", bg="#f0f0f0", wraplength=280).pack(pady=10, padx=10)

    def submit_test(self):
        total_questions = len(self.questions)
        score_per_question = 1000 / total_questions
        total_score = 0

        # Calculate score by comparing the user's selection to the correct answer
        for idx, question in enumerate(self.questions):
            selected = self.answer_vars[idx].get().strip()
            correct = question.get("answer_text", "").strip()
            if selected == correct:
                total_score += score_per_question

        final_score = round(total_score)
        if not messagebox.askyesno("Confirm Submission", f"Your score is {final_score} out of 1000.\nSubmit your test?"):
            return

        params = {"username": self.username, "score": final_score}
        try:
            response = requests.get(SUBMIT_URL, params=params, timeout=10)
            response.raise_for_status()
            messagebox.showinfo("Success", f"Test submitted successfully!\nServer Response:\n{response.text}")
        except Exception as e:
            messagebox.showerror("Error", f"Failed to submit test:\n{e}")
        finally:
            self.destroy()

if __name__ == "__main__":
    app = RorakakeTestApp()
    app.mainloop()
