import random
import os
import sys
import tkinter as tk
from tkinter import messagebox, ttk
import time


class HoverButton(tk.Button):
    def __init__(self, master, **kwargs):
        super().__init__(master, **kwargs)
        self.default_bg = self['bg']
        self.hover_bg = '#90CAF9'  # Light blue hover color

        self.bind('<Enter>', self.on_enter)
        self.bind('<Leave>', self.on_leave)

    def on_enter(self, e):
        self['bg'] = self.hover_bg
        # Slight grow effect
        self.config(relief=tk.RAISED)

    def on_leave(self, e):
        self['bg'] = self.default_bg
        self.config(relief=tk.FLAT)


def resource_path(relative_path):
    try:
        base_path = sys._MEIPASS
    except Exception:
        base_path = os.path.abspath(".")
    return os.path.join(base_path, relative_path)


def read_words_meanings(file_path):
    words = []
    meanings = []
    examples = []
    with open(file_path, 'r') as file:
        content = file.read().strip().split('\n\n')
        for entry in content:
            lines = [line.strip() for line in entry.strip().split('\n') if line.strip()]
            if len(lines) < 3:
                print(f"Skipping entry due to incorrect format: {entry}")
                continue
            word = lines[0].replace(":", "").strip()
            meaning_line = lines[1]
            example_line = lines[2]
            if not meaning_line.startswith("Meaning: ") or not example_line.startswith("Example: "):
                print(f"Skipping entry due to incorrect format: {entry}")
                continue
            meaning = meaning_line.replace("Meaning: ", "").strip()
            example = example_line.replace("Example: ", "").strip()
            words.append(word)
            meanings.append(meaning)
            examples.append(example)
    return words, meanings, examples


def read_fun_facts_from_file(file_path):
    with open(file_path, 'r') as file:
        fun_facts = [line.strip().strip('"').strip(',') for line in file if line.strip()]
    return fun_facts


def funny_message(fun_facts):
    return random.choice(fun_facts)


def create_quiz(words, meanings, examples, num_questions):
    question_set = set()
    quiz = []
    while len(quiz) < num_questions:
        index = random.randint(0, len(words) - 1)
        if index in question_set:
            continue
        question_set.add(index)
        word = words[index]
        meaning = meanings[index]
        example = examples[index]
        options = [meaning]
        wrong_meanings = random.sample([m for m in meanings if m != meaning], 2)
        options.extend(wrong_meanings)
        random.shuffle(options)
        correct_index = options.index(meaning)
        quiz.append((word, options, example, correct_index))
    random.shuffle(quiz)
    return quiz


def animate_widget(widget, start_y, end_y, duration=0.3):
    frames = 20
    delta = (end_y - start_y) / frames

    def update_position(frame):
        if frame < frames:
            current_y = start_y + (delta * frame)
            widget.place(rely=current_y)
            root.after(int(duration * 1000 / frames), lambda: update_position(frame + 1))

    update_position(0)


def show_quiz_interface():
    global question_label, word_label, option1_button, option2_button, option3_button
    global joker_button, progress_bar, score_label, remaining_label, progress_var

    # Clear the question count selection interface
    for widget in root.winfo_children():
        widget.destroy()

    # Create container frame
    container = tk.Frame(root, bg="#f0f8ff")
    container.pack(expand=True, fill='both', padx=20, pady=20)

    # Create new frames with proper spacing
    top_frame = tk.Frame(container, bg="#f0f8ff")
    top_frame.pack(fill='x', pady=(0, 20))

    middle_frame = tk.Frame(container, bg="#f0f8ff")
    middle_frame.pack(fill='x', pady=20)

    bottom_frame = tk.Frame(container, bg="#f0f8ff")
    bottom_frame.pack(fill='x', pady=(20, 0))

    # Create and place the widgets with improved styling
    question_label = tk.Label(top_frame, text="Press Start to begin the quiz",
                              wraplength=400, justify="center",
                              font=("Arial", 16, "bold"), bg="#f0f8ff")
    question_label.pack(pady=10)

    word_label = tk.Label(top_frame, text="", wraplength=400, justify="center",
                          font=("Arial", 24, "bold"), fg="#1976D2", bg="#f0f8ff")
    word_label.pack(pady=10)

    # Style for option buttons
    option_style = {
        'font': ('Arial', 12),
        'width': 45,
        'height': 2,
        'bg': '#E3F2FD',
        'activebackground': '#90CAF9',
        'relief': tk.FLAT,
        'bd': 0
    }

    # Create option buttons with equal spacing
    option1_button = HoverButton(middle_frame, **option_style)
    option1_button.pack(pady=5)

    option2_button = HoverButton(middle_frame, **option_style)
    option2_button.pack(pady=5)

    option3_button = HoverButton(middle_frame, **option_style)
    option3_button.pack(pady=5)

    # Style for control buttons
    control_style = {
        'font': ('Arial', 12),
        'width': 15,
        'height': 1,
        'bg': '#2196F3',
        'fg': 'white',
        'activebackground': '#1976D2',
        'activeforeground': 'white',
        'relief': tk.FLAT,
        'bd': 0
    }

    joker_button = HoverButton(bottom_frame, text="Use Joker", command=use_joker, **control_style)
    joker_button.pack(pady=5)

    start_button = HoverButton(bottom_frame, text="Start Quiz", command=start_quiz, **control_style)
    start_button.pack(pady=10)

    # Modern progress bar style
    style = ttk.Style()
    style.configure("Custom.Horizontal.TProgressbar",
                    troughcolor='#E3F2FD',
                    background='#2196F3',
                    thickness=10)

    progress_var = tk.DoubleVar()
    progress_bar = ttk.Progressbar(bottom_frame,
                                   style="Custom.Horizontal.TProgressbar",
                                   variable=progress_var,
                                   maximum=100,
                                   length=300)
    progress_bar.pack(pady=10)

    # Status labels with modern styling
    score_label = tk.Label(bottom_frame, text="Score: 0",
                           font=("Arial", 14, "bold"),
                           fg="#1976D2",
                           bg="#f0f8ff")
    score_label.pack(pady=5)

    remaining_label = tk.Label(bottom_frame, text="Remaining: 0",
                               font=("Arial", 14, "bold"),
                               fg="#1976D2",
                               bg="#f0f8ff")
    remaining_label.pack(pady=5)


def create_question_count_selection():
    # Clear any existing widgets
    for widget in root.winfo_children():
        widget.destroy()

    # Create main container with padding
    container = tk.Frame(root, bg="#f0f8ff")
    container.pack(expand=True, fill='both', padx=40, pady=40)

    # Add title with animation
    title_label = tk.Label(container,
                           text="How many questions would you like to answer?",
                           font=("Arial", 20, "bold"),
                           fg="#1976D2",
                           bg="#f0f8ff",
                           pady=20)
    title_label.pack()

    # Create a frame for buttons
    button_frame = tk.Frame(container, bg="#f0f8ff")
    button_frame.pack(expand=True)

    # Style for question count buttons
    button_style = {
        'font': ('Arial', 14),
        'width': 20,
        'height': 1,
        'bg': '#E3F2FD',
        'activebackground': '#90CAF9',
        'relief': tk.FLAT,
        'bd': 0
    }

    # Add option buttons with animations
    questions_options = [5, 10, 15, 20]
    for i, count in enumerate(questions_options):
        btn = HoverButton(button_frame,
                          text=f"{count} Questions",
                          command=lambda c=count: select_question_count(c),
                          **button_style)
        # Calculate position for animation
        start_y = 1.0  # Start below the visible area
        end_y = 0.2 + (i * 0.15)  # Final position with spacing
        btn.place(relx=0.5, rely=start_y, anchor='center')
        # Delay each button's animation slightly
        root.after(i * 100, lambda w=btn, sy=start_y, ey=end_y: animate_widget(w, sy, ey))


def select_question_count(count):
    global num_questions
    num_questions = count
    show_quiz_interface()


def check_answer(selected_index, correct_index, example):
    global question_number, score, quiz, joker_button_state
    funny_threshold = 0.5
    funny = random.random() < funny_threshold

    if selected_index == correct_index:
        score += 1
        message = f"Correct!\n\nExample:\n{example}"
        if funny:
            message += f"\n\nFunFact: {funny_message(fun_facts)}"
        messagebox.showinfo("Result", message)
    else:
        score -= 1
        message = f"Wrong! The correct answer was: {quiz[question_number][1][correct_index]}.\n\nExample:\n{example}"
        if funny:
            message += f"\n\nP.S. {funny_message(fun_facts)}"
        messagebox.showinfo("Result", message)

    rounded_percentage = round((score / len(quiz)) * 100)
    score_label.config(text=f"Score: {rounded_percentage}% ({score})")
    question_number += 1
    administer_quiz()


def use_joker():
    global joker_used, question_number, joker_button_state
    if not joker_used and question_number < len(quiz) and not joker_button_state:
        word, options, example, correct_index = quiz[question_number]
        options_to_remove = [i for i in range(len(options)) if i != correct_index]
        option_to_remove = random.choice(options_to_remove)
        if option_to_remove == 0:
            option1_button.config(state="disabled", bg='#E0E0E0')
        elif option_to_remove == 1:
            option2_button.config(state="disabled", bg='#E0E0E0')
        elif option_to_remove == 2:
            option3_button.config(state="disabled", bg='#E0E0E0')
        joker_used = True
        joker_button_state = True
        joker_button.config(state="disabled", bg='#E0E0E0')


def start_quiz():
    global question_number, score, quiz, joker_used
    question_number = 0
    score = 0
    joker_used = False
    quiz = create_quiz(words, meanings, examples, num_questions)
    administer_quiz()


def administer_quiz():
    global question_number, score, quiz, joker_used, joker_button_state
    if question_number < len(quiz):
        word, options, example, correct_index = quiz[question_number]
        question_label.config(text=f"Question {question_number + 1}: What is the meaning of ")
        word_label.config(text=f"'{word}'")

        # Reset button states and colors
        option1_button.config(text=options[0], state="normal", bg='#E3F2FD')
        option2_button.config(text=options[1], state="normal", bg='#E3F2FD')
        option3_button.config(text=options[2], state="normal", bg='#E3F2FD')

        # Set button commands
        option1_button.config(command=lambda: check_answer(0, correct_index, example))
        option2_button.config(command=lambda: check_answer(1, correct_index, example))
        option3_button.config(command=lambda: check_answer(2, correct_index, example))

        progress_var.set((question_number + 1) / len(quiz) * 100)
        remaining_questions = len(quiz) - (question_number + 1)
        remaining_label.config(text=f"Remaining: {remaining_questions}")

        if not joker_used:
            joker_button.config(state="normal", bg='#2196F3')
        joker_button_state = False
    else:
        percentage_score = (score / len(quiz)) * 100
        rounded_percentage = round(percentage_score)
        joker_message = "You used the joker." if joker_used else "You did not use the joker."
        final_message = (
            f"🎉 Congratulations! 🎉\n\n"
            f"Your final score is {score}/{len(quiz)}.\n"
            f"That's {rounded_percentage}%!\n\n"
            f"{joker_message}\n\n"
            f"Thank you for taking the quiz with Sadra!"
            f"\n\nLast Fun Fact: {funny_message(fun_facts)}"
        )
        messagebox.showinfo("Quiz Completed", final_message)
        root.destroy()


if __name__ == '__main__':
    # Load resources
    funny_message_file_path = resource_path('funny_message.txt')
    words_meanings_file_path = resource_path('words_meanings.txt')

    if not os.path.exists(words_meanings_file_path):
        print(f"Error: {words_meanings_file_path} does not exist.")
        exit()

    words, meanings, examples = read_words_meanings(words_meanings_file_path)
    if not words:
        print("No valid entries found in the file.")
        exit()

    fun_facts = read_fun_facts_from_file(funny_message_file_path)
    # Create the main application window
    root = tk.Tk()
    root.title("Vocabulary Quiz")
    root.geometry("800x600")
    root.config(bg="#f0f8ff")

    # Initialize variables
    question_number = 0
    score = 0
    joker_used = False
    joker_button_state = False
    quiz = []
    num_questions = 10  # Default value, will be updated by user selection

    # Center the window on the screen
    screen_width = root.winfo_screenwidth()
    screen_height = root.winfo_screenheight()
    x = (screen_width - 800) // 2
    y = (screen_height - 600) // 2
    root.geometry(f"800x600+{x}+{y}")

    # Add window icon (if available)
    try:
        root.iconbitmap(resource_path('quiz_icon.ico'))
    except:
        pass  # Skip if icon file is not available

    # Configure custom styles for the application
    style = ttk.Style()

    # Configure the default button style
    style.configure("TButton",
                    font=("Arial", 12),
                    padding=10,
                    background="#2196F3",
                    foreground="white")

    # Configure a custom style for the progress bar
    style.configure("Custom.Horizontal.TProgressbar",
                    troughcolor='#E3F2FD',
                    background='#2196F3',
                    thickness=10,
                    borderwidth=0)

    # Add hover effects to the progress bar
    style.map("Custom.Horizontal.TProgressbar",
              background=[('active', '#1976D2')])

    # Configure grid weights for responsive layout
    root.grid_rowconfigure(0, weight=1)
    root.grid_rowconfigure(1, weight=1)
    root.grid_rowconfigure(2, weight=1)
    root.grid_columnconfigure(0, weight=1)

    # Create custom fonts for different elements
    title_font = ("Arial", 24, "bold")
    button_font = ("Arial", 12)
    label_font = ("Arial", 14)


    # Add keyboard shortcuts
    def handle_keyboard_input(event):
        if question_number < len(quiz):
            if event.char in ['1', '2', '3']:
                index = int(event.char) - 1
                if index == 0 and option1_button['state'] != 'disabled':
                    option1_button.invoke()
                elif index == 1 and option2_button['state'] != 'disabled':
                    option2_button.invoke()
                elif index == 2 and option3_button['state'] != 'disabled':
                    option3_button.invoke()
            elif event.char == 'j' and not joker_used and joker_button['state'] != 'disabled':
                joker_button.invoke()


    root.bind('<Key>', handle_keyboard_input)


    # Add smooth transition effects
    def fade_in(widget):
        alpha = 0
        widget.attributes('-alpha', alpha)

        def increase_alpha():
            nonlocal alpha
            if alpha < 1:
                alpha += 0.1
                widget.attributes('-alpha', alpha)
                widget.after(50, increase_alpha)

        increase_alpha()


    # Configure window properties
    root.resizable(True, True)  # Allow window resizing
    root.minsize(600, 400)  # Set minimum window size

    # Add modern window styling (if running on Windows)
    try:
        from ctypes import windll

        windll.shcore.SetProcessDpiAwareness(1)
    except:
        pass


    # Create a loading screen
    def show_loading_screen():
        loading_frame = tk.Frame(root, bg="#f0f8ff")
        loading_frame.place(relx=0.5, rely=0.5, anchor="center")

        loading_label = tk.Label(loading_frame,
                                 text="Loading Quiz...",
                                 font=title_font,
                                 fg="#1976D2",
                                 bg="#f0f8ff")
        loading_label.pack(pady=20)

        loading_bar = ttk.Progressbar(loading_frame,
                                      style="Custom.Horizontal.TProgressbar",
                                      length=200,
                                      mode='indeterminate')
        loading_bar.pack()
        loading_bar.start(15)

        # Simulate loading time
        root.after(1500, lambda: [loading_frame.destroy(), create_question_count_selection()])


    # Add error handling for the main loop
    def on_error(error_type, value, traceback):
        messagebox.showerror("Error",
                             "An unexpected error occurred. The application will restart.\n\n"
                             f"Error: {str(value)}")
        root.destroy()


    root.report_callback_exception = on_error

    # Start with loading screen
    root.after(100, show_loading_screen)

    # Start the main event loop
    try:
        root.mainloop()
    except Exception as e:
        print(f"Error in main loop: {str(e)}")
        sys.exit(1)



its have problem in show number question wan tanswer options