from typing import Dict, Optional
from PySide6.QtWidgets import QApplication, QDialog, QVBoxLayout, QComboBox, QPushButton
from PySide6.QtCore import QSettings
from src.resources.themes.styles import themes
from src.resources.themes.colors import (
    WHITE, BLACK,
    BG_ITEM_DEFAULT, BORDER_ITEM_DEFAULT, BG_ITEM_SELECTED_DEFAULT,
    BG_ITEM_HACKTHEBOX, BORDER_BUTTON_HACKTHEBOX, BG_ITEM_SELECTED_HACKTHEBOX,
    BG_ITEM_SUNSET, BORDER_ITEM_SUNSET, BG_ITEM_SELECTED_SUNSET
)


class ThemeManager:
    """
    Manages application themes and related settings.
    """

    def __init__(self) -> None:
        self.settings: QSettings = QSettings('Rocket', 'ThemeSettings')
        self.theme_styles: Dict[str, Dict[str, str]] = {
            'Default': {
                'background_color': BG_ITEM_DEFAULT,
                'text_color': WHITE,
                'selection_background_color': BG_ITEM_SELECTED_DEFAULT,
                'selection_text_color': BLACK,
                'border_color': BORDER_ITEM_DEFAULT
            },
            'Hack The Box': {
                'background_color': BG_ITEM_HACKTHEBOX,
                'text_color': WHITE,
                'selection_background_color': BG_ITEM_SELECTED_HACKTHEBOX,
                'selection_text_color': WHITE,
                'border_color': BORDER_BUTTON_HACKTHEBOX
            },
            'Sunset': {
                'background_color': BG_ITEM_SUNSET,
                'text_color': WHITE,
                'selection_background_color': BG_ITEM_SELECTED_SUNSET,
                'selection_text_color': BLACK,
                'border_color': BORDER_ITEM_SUNSET
            }
        }

    @staticmethod
    def apply_theme(app: QApplication, theme_name: str) -> None:
        app.setStyleSheet(themes.get(theme_name, themes['Hack The Box']))

    def get_current_theme(self) -> str:
        theme_value = self.settings.value('current_theme', 'Hack The Box')
        current_theme = str(theme_value) if theme_value is not None else 'Hack The Box'
        
        # If the saved theme no longer exists, reset to Default
        if current_theme not in self.theme_styles:
            self.set_current_theme('Hack The Box')
            return 'Hack The Box'
            
        return current_theme

    def set_current_theme(self, theme_name: str) -> None:
        self.settings.setValue('current_theme', theme_name)

    def change_theme(self, theme_name: str) -> None:
        app: Optional[QApplication] = QApplication.instance()
        if app is None:
            print("No QApplication instance found")
            return

        self.apply_theme(app, theme_name)
        self.set_current_theme(theme_name)
        self.apply_combo_box_style(theme_name)

    def get_theme_style(self, theme_name: str) -> Dict[str, str]:
        if theme_name not in self.theme_styles:
            print(f"Theme '{theme_name}' not found. Using the Default theme.")
            return self.theme_styles['Default']
        return self.theme_styles[theme_name]

    def apply_combo_box_style(self, theme_name: str) -> None:
        selected_theme: Dict[str, str] = self.get_theme_style(theme_name)

        combo_box_style: str = f"""
            QComboBox {{
                padding: 5px;
                border: 1px solid {selected_theme['border_color']};
                border-radius: 10px;
                background-color: {selected_theme['background_color']};
                color: {selected_theme['text_color']};
            }}
            QComboBox::drop-down {{
                border-top-right-radius: 10px;
                border-bottom-right-radius: 10px;
                background-color: {selected_theme['background_color']};
            }}
            QComboBox QAbstractItemView {{
                selection-background-color: {selected_theme['selection_background_color']};
                selection-color: {selected_theme['selection_text_color']};
            }}
        """

        app: Optional[QApplication] = QApplication.instance()
        if app is not None:
            app.setStyleSheet(app.styleSheet() + combo_box_style)

    def get_available_themes(self) -> list[str]:
        return list(self.theme_styles.keys())

    def show_theme_selector(self) -> None:
        theme_dialog: QDialog = QDialog()
        theme_dialog.setWindowTitle('Select Theme')
        theme_dialog.setFixedSize(250, 150)
        layout: QVBoxLayout = QVBoxLayout()

        theme_selector: QComboBox = QComboBox()
        theme_selector.addItems(self.get_available_themes())

        current_theme: str = self.get_current_theme()
        theme_selector.setCurrentText(current_theme)

        theme_selector.currentTextChanged.connect(
            lambda: self.change_theme(theme_selector.currentText())
        )
        layout.addWidget(theme_selector)

        apply_button: QPushButton = QPushButton('Apply')
        apply_button.clicked.connect(theme_dialog.accept)
        layout.addWidget(apply_button)

        theme_dialog.setLayout(layout)
        theme_dialog.exec()
