"""PySide2 GUI version of quizbase application."""

from __future__ import annotations

import json
import logging
import os
import sys
from dataclasses import dataclass, field
from pathlib import Path
from typing import ClassVar

import PySide2
from PySide2.QtCore import Qt
from PySide2.QtGui import QCloseEvent
from PySide2.QtWidgets import (
    QAbstractItemView,
    QApplication,
    QButtonGroup,
    QCheckBox,
    QComboBox,
    QDialog,
    QDialogButtonBox,
    QFileDialog,
    QFormLayout,
    QGroupBox,
    QHBoxLayout,
    QLabel,
    QLineEdit,
    QListWidget,
    QMainWindow,
    QMessageBox,
    QPushButton,
    QRadioButton,
    QScrollArea,
    QTabWidget,
    QTextEdit,
    QVBoxLayout,
    QWidget,
)

from .cli import (
    AdaptiveQuizSession,
    EssayQuestion,
    FillBlankQuestion,
    MultipleChoiceQuestion,
    Question,
    QuizResult,
    QuizSession,
    TrueFalseQuestion,
    create_sample_quiz_data,
)

logging.basicConfig(level=logging.INFO, format="%(message)s")
logger = logging.getLogger(__name__)

# Set Qt platform plugin path for Windows
qt_dir = Path(PySide2.__file__).parent
plugin_path = str(qt_dir / "plugins" / "platforms")
os.environ["QT_QPA_PLATFORM_PLUGIN_PATH"] = plugin_path


_WRONG_ANSWERS_FILE = Path.home() / ".pytola" / "wrong_answers.json"


@dataclass
class QuizConfig:
    """Quiz GUI configuration with persistence support."""

    window_width: int = 1000
    window_height: int = 700
    window_x: int = 100
    window_y: int = 100
    random_order: bool = False
    wrong_answers_file: str = str(_WRONG_ANSWERS_FILE)
    recent_files: list[str] = field(default_factory=list)

    def __post_init__(self) -> None:
        """Initialize configuration after creation."""
        if self.recent_files is None:
            self.recent_files = []


class ConfigManager:
    """Manage GUI configuration persistence using dataclass pattern."""

    MAX_RECENT_ITEMS: ClassVar[int] = 10
    DEFAULT_CONFIG: ClassVar[QuizConfig] = QuizConfig()

    def __init__(self, config_file: Path | None = None) -> None:
        """Initialize configuration manager."""
        if config_file is None:
            config_dir = Path.home() / ".pytola"
            config_dir.mkdir(exist_ok=True)
            config_file = config_dir / "quizbase_gui.json"
        self.config_file = config_file
        self.config = self._load_config()

    def _load_config(self) -> QuizConfig:
        """Load configuration from file."""
        if self.config_file.exists():
            try:
                with Path(self.config_file).open(encoding="utf-8") as f:
                    config_data = json.load(f)
                # Create config from loaded data, falling back to defaults
                return QuizConfig(
                    window_width=config_data.get(
                        "window_width",
                        self.DEFAULT_CONFIG.window_width,
                    ),
                    window_height=config_data.get(
                        "window_height",
                        self.DEFAULT_CONFIG.window_height,
                    ),
                    window_x=config_data.get("window_x", self.DEFAULT_CONFIG.window_x),
                    window_y=config_data.get("window_y", self.DEFAULT_CONFIG.window_y),
                    random_order=config_data.get(
                        "random_order",
                        self.DEFAULT_CONFIG.random_order,
                    ),
                    wrong_answers_file=config_data.get(
                        "wrong_answers_file",
                        self.DEFAULT_CONFIG.wrong_answers_file,
                    ),
                    recent_files=config_data.get(
                        "recent_files",
                        self.DEFAULT_CONFIG.recent_files.copy(),
                    ),
                )
            except (OSError, json.JSONDecodeError) as e:
                logger.warning(f"Failed to load config: {e}. Using defaults.")
        return QuizConfig()

    def save_config(self) -> None:
        """Save configuration to file."""
        try:
            config_dict = {
                "window_width": self.config.window_width,
                "window_height": self.config.window_height,
                "window_x": self.config.window_x,
                "window_y": self.config.window_y,
                "random_order": self.config.random_order,
                "wrong_answers_file": self.config.wrong_answers_file,
                "recent_files": self.config.recent_files,
            }
            with Path(self.config_file).open("w", encoding="utf-8") as f:
                json.dump(config_dict, f, indent=2, ensure_ascii=False)
        except OSError as e:
            logger.warning(f"Failed to save config: {e}")

    def get(self, key: str, default: object = None) -> object:
        """Get configuration value."""
        return getattr(self.config, key, default)

    def set(self, key: str, value: object) -> None:
        """Set configuration value."""
        if hasattr(self.config, key):
            setattr(self.config, key, value)

    def add_recent_file(self, file_path: str) -> None:
        """Add file to recent files list."""
        recent_files = self.config.recent_files.copy()
        recent_files = [f for f in recent_files if f != file_path]
        recent_files.insert(0, file_path)
        recent_files = recent_files[: self.MAX_RECENT_ITEMS]
        self.config.recent_files = recent_files

    def get_config(self) -> QuizConfig:
        """Get configuration as QuizConfig dataclass."""
        return self.config


class QuestionAnswerWidget(QWidget):
    """Widget for answering questions based on question type."""

    # Mapping of question types to their attribute names that need cleanup
    QUESTION_ATTRIBUTES: ClassVar[dict[str, list[str]]] = {
        "multiple_choice": ["radio_buttons", "checkboxes", "radio_button_group"],
        "fill_blank": ["text_input"],
        "true_false": ["true_radio", "false_radio"],
        "essay": ["text_edit"],
    }

    def __init__(self, parent: QWidget | None = None) -> None:
        """Initialize question answer widget."""
        super().__init__(parent)
        self.question: Question | None = None
        self.layout = QVBoxLayout(self)
        self.current_answer_widget: QWidget | None = None

    def _cleanup_question_attributes(self) -> None:
        """Clean up attributes from previous question type."""
        attrs_to_remove = [attr for attrs in self.QUESTION_ATTRIBUTES.values() for attr in attrs]
        for attr in attrs_to_remove:
            if hasattr(self, attr):
                delattr(self, attr)

    def _create_answer_widget(self, question: Question) -> QWidget:
        """Create appropriate answer widget based on question type."""
        widget_map: dict[type, callable] = {
            MultipleChoiceQuestion: self._create_multiple_choice_widget,
            FillBlankQuestion: self._create_fill_blank_widget,
            TrueFalseQuestion: self._create_true_false_widget,
            EssayQuestion: self._create_essay_widget,
        }

        for question_type, creator_func in widget_map.items():
            if isinstance(question, question_type):
                return creator_func(question)

        return QLabel("Unknown question type")

    def set_question(self, question: Question) -> None:
        """Set question and create appropriate answer widget."""
        self.question = question

        # Clear existing widget
        if self.current_answer_widget:
            self.layout.removeWidget(self.current_answer_widget)  # type: ignore
            self.current_answer_widget.deleteLater()
            self.current_answer_widget = None

        # Clean up old attributes that belong to the previous question type
        self._cleanup_question_attributes()

        # Create appropriate answer widget based on question type
        widget = self._create_answer_widget(question)

        self.current_answer_widget = widget
        self.layout.addWidget(widget)  # type: ignore

    def _create_multiple_choice_widget(
        self,
        question: MultipleChoiceQuestion,
    ) -> QWidget:
        """Create widget for multiple choice questions."""
        widget = QWidget()
        layout = QVBoxLayout(widget)

        if question.allow_multiple:
            # Checkboxes for multiple selections
            self.checkboxes: list[QCheckBox] = []
            for i, option in enumerate(question.options):
                checkbox = QCheckBox(option)
                checkbox.setProperty("option_index", i)
                self.checkboxes.append(checkbox)
                layout.addWidget(checkbox)
        else:
            # Radio buttons for single selection
            self.radio_buttons: list[QRadioButton] = []
            # Create a button group for radio buttons to ensure mutual exclusivity
            self.radio_button_group = QButtonGroup(self)
            for i, option in enumerate(question.options):
                radio = QRadioButton(option)
                radio.setProperty("option_index", i)
                self.radio_buttons.append(radio)
                self.radio_button_group.addButton(
                    radio,
                    i,
                )  # Add to button group with ID
                layout.addWidget(radio)

        return widget

    def _create_fill_blank_widget(self, question: FillBlankQuestion) -> QWidget:
        """Create widget for fill in the blank questions."""
        widget = QWidget()
        layout = QHBoxLayout(widget)

        label = QLabel("Answer:")
        self.text_input = QLineEdit()
        self.text_input.setPlaceholderText("Enter your answer here...")

        layout.addWidget(label)
        layout.addWidget(self.text_input)

        return widget

    def _create_true_false_widget(self, question: TrueFalseQuestion) -> QWidget:
        """Create widget for true/false questions."""
        widget = QWidget()
        layout = QHBoxLayout(widget)

        self.true_radio = QRadioButton("True")
        self.false_radio = QRadioButton("False")
        self.true_radio.setProperty("answer", True)
        self.false_radio.setProperty("answer", False)

        layout.addWidget(self.true_radio)
        layout.addWidget(self.false_radio)

        return widget

    def _create_essay_widget(self, question: EssayQuestion) -> QWidget:
        """Create widget for essay questions."""
        widget = QWidget()
        layout = QVBoxLayout(widget)

        label = QLabel("Your Answer:")
        label.setStyleSheet("font-weight: bold; margin-top: 10px;")

        self.text_edit = QTextEdit()
        self.text_edit.setPlaceholderText("Type your answer here...")
        self.text_edit.setMinimumHeight(200)

        if question.keywords:
            hint = QLabel(f"Key points to cover: {', '.join(question.keywords)}")
            hint.setStyleSheet("color: gray; font-style: italic; margin-bottom: 5px;")
            layout.addWidget(hint)

        layout.addWidget(label)
        layout.addWidget(self.text_edit)

        return widget

    def get_answer(self) -> object:
        """Get user's answer."""
        if isinstance(self.question, MultipleChoiceQuestion):
            if self.question.allow_multiple:
                return [cb.property("option_index") for cb in getattr(self, "checkboxes", []) if cb.isChecked()]
            for radio in getattr(self, "radio_buttons", []):
                if radio.isChecked():
                    return radio.property("option_index")
            return None
        if isinstance(self.question, FillBlankQuestion):
            return getattr(self, "text_input", QLineEdit()).text()
        if isinstance(self.question, TrueFalseQuestion):
            if getattr(self, "true_radio", None) and self.true_radio.isChecked():
                return True
            if getattr(self, "false_radio", None) and self.false_radio.isChecked():
                return False
            return None
        if isinstance(self.question, EssayQuestion):
            return getattr(self, "text_edit", QTextEdit()).toPlainText()
        return None

    def _clear_multiple_choice_answer(self) -> None:
        """Clear multiple choice answer."""
        if self.question.allow_multiple:
            # Clear checkboxes
            for cb in getattr(self, "checkboxes", []):
                cb.setChecked(False)
        else:
            # Clear radio buttons
            self._clear_radio_buttons()

    def _clear_radio_buttons(self) -> None:
        """Clear radio button selections with proper signal handling."""
        radio_buttons = getattr(self, "radio_buttons", None)
        button_group = getattr(self, "radio_button_group", None)

        if button_group:
            # Temporarily disable the exclusive property of the button group
            button_group.setExclusive(False)

        if radio_buttons:
            # For radio buttons, we need to temporarily block signals
            # to clear all selections properly
            for radio in radio_buttons:
                radio.blockSignals(True)
                radio.setChecked(False)
                radio.blockSignals(False)

        if button_group:
            # Re-enable exclusive property after clearing
            button_group.setExclusive(True)

        # Force processing of events to ensure UI updates
        self._process_qt_events()

    def _clear_true_false_answer(self) -> None:
        """Clear true/false answer."""
        if getattr(self, "true_radio", None):
            self.true_radio.blockSignals(True)
            self.true_radio.setChecked(False)
            self.true_radio.blockSignals(False)
        if getattr(self, "false_radio", None):
            self.false_radio.blockSignals(True)
            self.false_radio.setChecked(False)
            self.false_radio.blockSignals(False)
        # Force processing of events to ensure UI updates
        self._process_qt_events()

    def _clear_fill_blank_answer(self) -> None:
        """Clear fill in the blank answer."""
        getattr(self, "text_input", QLineEdit()).clear()

    def _clear_essay_answer(self) -> None:
        """Clear essay answer."""
        getattr(self, "text_edit", QTextEdit()).clear()

    def _process_qt_events(self) -> None:
        """Process Qt events to ensure UI updates."""
        from PySide2.QtWidgets import QApplication

        app = QApplication.instance()
        if app:
            app.processEvents()

    def clear_answer(self) -> None:
        """Clear user's answer."""
        if isinstance(self.question, MultipleChoiceQuestion):
            self._clear_multiple_choice_answer()
        elif isinstance(self.question, FillBlankQuestion):
            self._clear_fill_blank_answer()
        elif isinstance(self.question, TrueFalseQuestion):
            self._clear_true_false_answer()
        elif isinstance(self.question, EssayQuestion):
            self._clear_essay_answer()


class WrongAnswersDialog(QDialog):
    """Dialog to display wrong answers."""

    def __init__(self, results: list[QuizResult], parent: QWidget | None = None) -> None:
        """Initialize wrong answers dialog."""
        super().__init__(parent)
        self.results = results
        self.setWindowTitle("Wrong Answers Review")
        self.setMinimumSize(800, 600)
        self._setup_ui()

    def _setup_ui(self) -> None:
        """Set up dialog UI."""
        layout = QVBoxLayout(self)

        # Scroll area for results
        scroll = QScrollArea()
        scroll.setWidgetResizable(True)

        content_widget = QWidget()
        content_layout = QVBoxLayout(content_widget)

        for i, result in enumerate(self.results, 1):
            result_group = QGroupBox(f"Question {i}")
            result_layout = QVBoxLayout()

            # Question
            question_label = QLabel(f"<b>Question:</b> {result.question.question_text}")
            question_label.setWordWrap(True)
            result_layout.addWidget(question_label)

            # User answer
            user_answer_label = QLabel(f"<b>Your Answer:</b> {result.user_answer}")
            user_answer_label.setWordWrap(True)
            result_layout.addWidget(user_answer_label)

            # Explanation
            explanation_label = QLabel(f"<b>Explanation:</b> {result.explanation}")
            explanation_label.setWordWrap(True)
            explanation_label.setStyleSheet("color: red;")
            result_layout.addWidget(explanation_label)

            result_group.setLayout(result_layout)
            content_layout.addWidget(result_group)

        scroll.setWidget(content_widget)
        layout.addWidget(scroll)

        # Close button
        button_box = QDialogButtonBox(QDialogButtonBox.Close)
        button_box.rejected.connect(self.accept)
        layout.addWidget(button_box)


class QuizBaseMainWindow(QMainWindow):
    """Main window for QuizBase GUI application."""

    def __init__(self) -> None:
        """Initialize main window."""
        super().__init__()
        self.config_manager = ConfigManager()
        self.config = self.config_manager.get_config()
        self.session: QuizSession | None = None
        self.current_result: QuizResult | None = None
        self._setup_ui()
        self._load_settings()

    def _setup_ui(self) -> None:
        """Set up user interface."""
        self.setWindowTitle("QuizBase - Universal Quiz System")
        self.setMinimumSize(900, 700)

        # Central widget
        central_widget = QWidget()
        self.setCentralWidget(central_widget)

        # Main layout
        main_layout = QVBoxLayout(central_widget)

        # Top toolbar
        toolbar_layout = QHBoxLayout()

        # Open file button
        self.open_button = QPushButton("Open Quiz File")
        self.open_button.clicked.connect(self._open_quiz_file)
        toolbar_layout.addWidget(self.open_button)

        # Recent files dropdown
        self.recent_combo = QComboBox()
        self.recent_combo.setMinimumWidth(300)
        self.recent_combo.currentIndexChanged.connect(self._load_recent_file)
        toolbar_layout.addWidget(self.recent_combo)

        # Random order checkbox
        self.random_checkbox = QCheckBox("Random Order")
        self.random_checkbox.setChecked(self.config.random_order)
        self.random_checkbox.stateChanged.connect(self._on_random_changed)
        toolbar_layout.addWidget(self.random_checkbox)

        # Adaptive mode checkbox
        self.adaptive_checkbox = QCheckBox("Adaptive Mode")
        self.adaptive_checkbox.setChecked(False)
        self.adaptive_checkbox.stateChanged.connect(self._on_adaptive_changed)
        toolbar_layout.addWidget(self.adaptive_checkbox)

        toolbar_layout.addStretch()

        # Create sample button
        self.create_sample_button = QPushButton("Create Sample")
        self.create_sample_button.clicked.connect(self._create_sample_quiz)
        toolbar_layout.addWidget(self.create_sample_button)

        main_layout.addLayout(toolbar_layout)

        # Tab widget
        self.tab_widget = QTabWidget()
        main_layout.addWidget(self.tab_widget)

        # Quiz tab
        self.quiz_tab = self._create_quiz_tab()
        self.tab_widget.addTab(self.quiz_tab, "Quiz")

        # Summary tab
        self.summary_tab = self._create_summary_tab()
        self.tab_widget.addTab(self.summary_tab, "Summary")

        # Wrong answers tab
        self.wrong_tab = self._create_wrong_answers_tab()
        self.tab_widget.addTab(self.wrong_tab, "Wrong Answers")

        # Status bar
        self.status_label = QLabel("No quiz loaded")
        self.statusBar().addWidget(self.status_label)

        # Initially disable tabs
        self._set_quiz_enabled(enabled=False)

    def _create_quiz_tab(self) -> QWidget:
        """Create quiz tab."""
        widget = QWidget()
        layout = QVBoxLayout(widget)

        # Progress info
        progress_layout = QHBoxLayout()
        self.progress_label = QLabel("Progress: - / -")
        progress_layout.addWidget(self.progress_label)
        progress_layout.addStretch()

        # Score info
        self.score_label = QLabel("Score: 0 / 0")
        progress_layout.addWidget(self.score_label)

        layout.addLayout(progress_layout)

        # Question info
        info_group = QGroupBox("Question Information")
        info_layout = QFormLayout()

        self.question_type_label = QLabel("-")
        self.question_points_label = QLabel("-")

        info_layout.addRow("Type:", self.question_type_label)
        info_layout.addRow("Points:", self.question_points_label)
        info_group.setLayout(info_layout)
        layout.addWidget(info_group)

        # Question text
        question_group = QGroupBox("Question")
        question_layout = QVBoxLayout()
        self.question_text_label = QLabel("No question loaded")
        self.question_text_label.setWordWrap(True)
        self.question_text_label.setStyleSheet(
            "font-size: 14px; font-weight: bold; margin: 10px;",
        )
        question_layout.addWidget(self.question_text_label)
        question_group.setLayout(question_layout)
        layout.addWidget(question_group)

        # Answer area
        answer_group = QGroupBox("Your Answer")
        answer_layout = QVBoxLayout()
        self.answer_widget = QuestionAnswerWidget()
        answer_layout.addWidget(self.answer_widget)
        answer_group.setLayout(answer_layout)
        layout.addWidget(answer_group)

        # Result area
        self.result_label = QLabel()
        self.result_label.setWordWrap(True)
        self.result_label.setStyleSheet("padding: 10px; margin: 10px;")
        layout.addWidget(self.result_label)

        # Buttons
        button_layout = QHBoxLayout()

        self.submit_button = QPushButton("Submit Answer")
        self.submit_button.setEnabled(False)
        self.submit_button.clicked.connect(self._submit_answer)
        button_layout.addWidget(self.submit_button)

        self.next_button = QPushButton("Next Question")
        self.next_button.setEnabled(False)
        self.next_button.clicked.connect(self._next_question)
        button_layout.addWidget(self.next_button)

        self.finish_button = QPushButton("Finish Quiz")
        self.finish_button.setEnabled(False)
        self.finish_button.clicked.connect(self._finish_quiz)
        button_layout.addWidget(self.finish_button)

        self.reset_button = QPushButton("Reset Quiz")
        self.reset_button.setEnabled(False)
        self.reset_button.clicked.connect(self._reset_quiz)
        button_layout.addWidget(self.reset_button)

        layout.addLayout(button_layout)

        return widget

    def _create_summary_tab(self) -> QWidget:
        """Create summary tab."""
        widget = QWidget()
        layout = QVBoxLayout(widget)

        # Summary text
        self.summary_text = QTextEdit()
        self.summary_text.setReadOnly(True)
        self.summary_text.setPlainText("Quiz summary will appear here...")
        layout.addWidget(self.summary_text)

        return widget

    def _create_wrong_answers_tab(self) -> QWidget:
        """Create wrong answers tab."""
        widget = QWidget()
        layout = QVBoxLayout(widget)

        # Instructions
        instruction = QLabel(
            "Wrong answers will be displayed here after quiz completion.",
        )
        layout.addWidget(instruction)

        # Wrong answers list
        self.wrong_answers_list = QListWidget()
        self.wrong_answers_list.setSelectionMode(QAbstractItemView.SingleSelection)
        layout.addWidget(self.wrong_answers_list)

        # View detail button
        self.view_detail_button = QPushButton("View Details")
        self.view_detail_button.setEnabled(False)
        self.view_detail_button.clicked.connect(self._view_wrong_answer_detail)
        layout.addWidget(self.view_detail_button)

        return widget

    def _set_quiz_enabled(self, *, enabled: bool) -> bool:
        """Enable or disable quiz-related controls."""
        self.submit_button.setEnabled(enabled)
        self.next_button.setEnabled(enabled)
        self.finish_button.setEnabled(enabled)
        self.reset_button.setEnabled(enabled)
        return enabled

    def _load_settings(self) -> None:
        """Load window settings."""
        self.resize(self.config.window_width, self.config.window_height)
        self.move(self.config.window_x, self.config.window_y)
        self._update_recent_files()

    def _save_settings(self) -> None:
        """Save window settings."""
        self.config_manager.set("window_width", self.width())
        self.config_manager.set("window_height", self.height())
        self.config_manager.set("window_x", self.x())
        self.config_manager.set("window_y", self.y())
        self.config_manager.set("random_order", self.random_checkbox.isChecked())
        self.config_manager.save_config()

    def _update_recent_files(self) -> None:
        """Update recent files dropdown."""
        self.recent_combo.clear()
        self.recent_combo.addItem("-- Recent Files --", None)
        for file_path in self.config.recent_files or []:
            self.recent_combo.addItem(Path(file_path).name, file_path)

    def _open_quiz_file(self) -> None:
        """Open quiz file dialog."""
        file_path, _ = QFileDialog.getOpenFileName(
            self,
            "Open Quiz File",
            "",
            "JSON Files (*.json);;All Files (*)",
        )

        if file_path:
            self._load_quiz(file_path)

    def _load_recent_file(self, index: int) -> None:
        """Load recently used file."""
        if index > 0:  # Skip placeholder
            file_path = self.recent_combo.currentData()
            if file_path:
                self._load_quiz(file_path)
            # Reset selection
            self.recent_combo.setCurrentIndex(0)

    def _load_quiz(self, file_path: str) -> None:
        """Load quiz from file."""
        try:
            # Check if adaptive mode is enabled
            if self.adaptive_checkbox.isChecked():
                self.session = AdaptiveQuizSession(
                    random_order=self.random_checkbox.isChecked(),
                )
                # Load performance history if available
                self.session.load_performance_history()
            else:
                self.session = QuizSession(
                    random_order=self.random_checkbox.isChecked(),
                )

            self.session.load_from_json(file_path)

            self.config_manager.add_recent_file(file_path)
            self._update_recent_files()

            self._set_quiz_enabled(enabled=True)
            self.status_label.setText(f"Quiz loaded: {Path(file_path).name}")
            self.tab_widget.setCurrentIndex(0)

            self._load_current_question()
            self._update_summary()

        except (OSError, json.JSONDecodeError, ValueError) as e:
            QMessageBox.critical(self, "Error", f"Failed to load quiz: {e}")

    def _create_sample_quiz(self) -> None:
        """Create sample quiz data."""
        file_path, _ = QFileDialog.getSaveFileName(
            self,
            "Save Sample Quiz",
            "sample_quiz.json",
            "JSON Files (*.json)",
        )

        if file_path:
            try:
                create_sample_quiz_data(file_path)
                self._load_quiz(file_path)
                QMessageBox.information(
                    self,
                    "Success",
                    "Sample quiz created successfully!",
                )
            except (OSError, json.JSONDecodeError, ValueError) as e:
                QMessageBox.critical(
                    self,
                    "Error",
                    f"Failed to create sample quiz: {e}",
                )

    def _on_random_changed(self, state: int) -> None:
        """Handle random order checkbox change."""
        if self.session and not self.session.results:
            # Only reset if no answers yet
            self.session.random_order = state == Qt.Checked
            self.session.reset()

    def _on_adaptive_changed(self, state: int) -> None:
        """Handle adaptive mode checkbox change."""
        if self.session and hasattr(self.session, "adaptive_mode") and not self.session.results:
            # Only reset if no answers yet
            self.session.adaptive_mode = state == Qt.Checked
            self.session.reset()

    def _load_current_question(self) -> None:
        """Load current question into UI."""
        if not self.session:
            return

        question = self.session.get_current_question()

        if question is None:
            self._finish_quiz()
            return

        # Update question info
        self.question_type_label.setText(question.question_type.value)
        self.question_points_label.setText(str(question.points))
        self.question_text_label.setText(question.question_text)

        # Load answer widget
        self.answer_widget.set_question(question)

        # Update progress
        self._update_progress()

        # Clear result
        self.result_label.clear()
        self.result_label.setStyleSheet("padding: 10px; margin: 10px;")

        # Enable submit, disable next
        self.submit_button.setEnabled(True)
        self.next_button.setEnabled(False)

    def _update_progress(self) -> None:
        """Update progress display."""
        if not self.session:
            return

        summary = self.session.get_summary()
        self.progress_label.setText(
            f"Progress: {summary['answered']} / {summary['total_questions']}",
        )
        self.score_label.setText(
            f"Score: {summary['earned_points']:.1f} / {summary['total_points']:.1f}",
        )

    def _submit_answer(self) -> None:
        """Submit answer for current question."""
        if not self.session:
            return

        answer = self.answer_widget.get_answer()

        if answer is None:
            QMessageBox.warning(self, "Warning", "Please provide an answer.")
            return

        # Submit to session
        self.current_result = self.session.submit_answer(answer)

        if self.current_result:
            # Display result
            if self.current_result.is_correct:
                self.result_label.setText(
                    f"✓ Correct!\n{self.current_result.explanation}",
                )
                self.result_label.setStyleSheet(
                    "background-color: #d4edda; color: #155724; padding: 10px; margin: 10px; border-radius: 5px;",
                )
            else:
                self.result_label.setText(
                    f"✗ Incorrect!\n{self.current_result.explanation}",
                )
                self.result_label.setStyleSheet(
                    "background-color: #f8d7da; color: #721c24; padding: 10px; margin: 10px; border-radius: 5px;",
                )

            # Update progress
            self._update_progress()
            self._update_summary()

            # Disable submit, enable next
            self.submit_button.setEnabled(False)
            self.answer_widget.clear_answer()

            if not self.session.is_finished():
                # Automatically advance to next question after a brief delay
                self._load_current_question()  # Auto-advance to next question
            else:
                self.finish_button.setEnabled(True)
                self.next_button.setEnabled(False)

    def _next_question(self) -> None:
        """Load next question."""
        self._load_current_question()

    def _finish_quiz(self) -> None:
        """Finish quiz and show summary."""
        if not self.session:
            return

        # Save wrong answers
        wrong_answers_file = self.config_manager.get(
            "wrong_answers_file",
            str(_WRONG_ANSWERS_FILE),
        )
        self.session.wrong_answer_file = wrong_answers_file
        self.session.save_wrong_answers()

        # Update summary tab
        self._update_summary()
        self._update_wrong_answers()

        # Switch to summary tab
        self.tab_widget.setCurrentIndex(1)

        # Show completion message
        summary = self.session.get_summary()
        message = (
            f"Quiz Completed!\n\n"
            f"Total Questions: {summary['total_questions']}\n"
            f"Correct: {summary['correct']}\n"
            f"Wrong: {summary['wrong']}\n"
            f"Score: {summary['earned_points']:.1f} / {summary['total_points']:.1f}\n"
            f"Accuracy: {summary['accuracy']:.1f}%"
        )
        QMessageBox.information(self, "Quiz Completed", message)

        self.status_label.setText("Quiz completed")

    def _update_summary(self) -> None:
        """Update summary tab."""
        if not self.session:
            return

        summary = self.session.get_summary()

        summary_text = (
            f"Quiz Summary\n"
            f"{'=' * 50}\n\n"
            f"Total Questions: {summary['total_questions']}\n"
            f"Answered: {summary['answered']}\n"
            f"Correct: {summary['correct']}\n"
            f"Wrong: {summary['wrong']}\n\n"
            f"Points Earned: {summary['earned_points']:.1f} / {summary['total_points']:.1f}\n"
            f"Accuracy: {summary['accuracy']:.1f}%\n"
            f"Status: {'Completed' if summary['is_finished'] else 'In Progress'}\n"
        )

        # Add question-by-question breakdown
        if self.session.results:
            summary_text += f"\n{'=' * 50}\n\nQuestion Breakdown:\n\n"
            for i, result in enumerate(self.session.results, 1):
                status = "✓" if result.is_correct else "✗"
                summary_text += f"{i}. {status} ({result.question.points} pts)\n"

        self.summary_text.setPlainText(summary_text)

    def _update_wrong_answers(self) -> None:
        """Update wrong answers tab."""
        if not self.session:
            return

        self.wrong_answers_list.clear()

        wrong_results = self.session.get_wrong_answers()

        if not wrong_results:
            self.wrong_answers_list.addItem("No wrong answers! Great job!")
            self.view_detail_button.setEnabled(False)
            return

        for i, result in enumerate(wrong_results, 1):
            self.wrong_answers_list.addItem(
                f"{i}. {result.question.question_text[:50]}...",
            )

        self.wrong_answers = wrong_results
        self.view_detail_button.setEnabled(True)

    def _view_wrong_answer_detail(self) -> None:
        """View detail of selected wrong answer."""
        if not hasattr(self, "wrong_answers") or not self.wrong_answers:
            return

        selected = self.wrong_answers_list.currentRow()
        if selected < 0 or selected >= len(self.wrong_answers):
            return

        result = self.wrong_answers[selected]
        dialog = WrongAnswersDialog([result], self)
        dialog.exec_()

    def _reset_quiz(self) -> None:
        """Reset quiz to beginning."""
        if not self.session:
            return

        reply = QMessageBox.question(
            self,
            "Reset Quiz",
            "Are you sure you want to reset this quiz? All progress will be lost.",
            QMessageBox.Yes | QMessageBox.No,
        )

        if reply == QMessageBox.Yes:
            self.session.reset(random_order=self.random_checkbox.isChecked())
            self.current_result = None
            self._load_current_question()
            self._update_summary()
            self.tab_widget.setCurrentIndex(0)
            self.status_label.setText("Quiz reset")

    def closeEvent(self, event: QCloseEvent) -> None:
        """Handle window close event."""
        self._save_settings()
        event.accept()


def main() -> None:
    """Run entry point for the GUI application.

    Quizbase Gui utility tool
    """
    app = QApplication(sys.argv)
    app.setStyle("Fusion")

    window = QuizBaseMainWindow()
    window.show()

    sys.exit(app.exec_())


if __name__ == "__main__":
    main()
