import json, os
from PyQt5.QtWidgets import (
    QDialog, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit, QPushButton,
    QCheckBox, QRadioButton, QButtonGroup, QFileDialog, QMessageBox,
    QGroupBox, QSizePolicy, QSpacerItem, QScrollArea, QWidget, QComboBox
)
from src.update_check import __version__

CONFIG_FILE = "games_config.json"
DEFAULTS = {
  "Minecraft: Java Edition": {
    "type": "flatpak",
    "exec_path": "org.prismlauncher.PrismLauncher",
    "instances_path": "/home/user/.var/app/org.prismlauncher.PrismLauncher/data/PrismLauncher/instances",
    "server_type": "none",
    "server_exec": "https://example.com/panel",
    "show": True
  },
  "Minecraft: Bedrock Edition": {
    "type": "flatpak",
    "exec_path": "io.mrarm.mcpelauncher",
    "server_type": "none",
    "server_exec": "https://example.com/panel",
    "show": True
  },
  "Minecraft Dungeons": {
    "exec_path": "1672970",
    "show": False
  },
  "Minecraft Legends": {
    "exec_path": "1928870",
    "show": False
  },
  "Minecraft: Story Mode": {
    "version": "steam",
    "exec_path": "1",
    "show": False
  },
  "Minecraft Story Mode: Season 2": {
    "version": "steam",
    "exec_path": "2",
    "show": False
  },
  "Minecraft: Xbox 360 Edition": {
    "exec_path": "/path/to/xenia",
    "rom_path": "/path/to/minecraft",
    "show": False
  },
  "Minecraft Classic": {
    "show": False
  },
  "Terraria": {
    "exec_path": "105600",
    "server_type": "none",
    "server_exec": "https://example.com/panel",
    "show": False
  },
  "Vintage Story": {
    "type": "flatpak",
    "exec_path": "at.vintagestory.VintageStory",
    "server_type": "none",
    "server_exec": "https://example.com/panel",
    "show": False
  },
  "Luanti": {
    "type": "flatpak",
    "exec_path": "org.luanti.luanti",
    "server_type": "none",
    "server_exec": "https://example.com/panel",
    "show": False
  },
  "ClassiCube": {
    "exec_path": "/path/to/classicube",
    "server_type": "none",
    "server_exec": "https://example.com/panel",
    "show": False
  },
  "update_check": True,
}

GAMES = [
    "Minecraft: Java Edition",
    "Minecraft: Bedrock Edition",
    "Minecraft Dungeons",
    "Minecraft Legends",
    "Minecraft: Story Mode",
    "Minecraft Story Mode: Season 2",
    "Minecraft: Xbox 360 Edition",
    "Minecraft Classic",
    "Terraria",
    "Vintage Story",
    "Luanti",
    "ClassiCube"
]
DESCRIPTIONS = {
    "Minecraft: Java Edition": "Utilizes MultiMC (or forks)",
    "Minecraft: Bedrock Edition": "Utilizes MCPE Launcher",
    "Minecraft Dungeons": "Launches Steam version",
    "Minecraft Legends": "Launches Steam version",
    "Minecraft: Story Mode": "Launches Steam or Lutris (GOG) version",
    "Minecraft Story Mode: Season 2": "Launches Steam or Lutris (GOG) version",
    "Minecraft: Xbox 360 Edition": "Utilizes Xenia Emulator",
    "Minecraft Classic": "Launches classic.minecraft.net in the browser",
    "Terraria": "Launches Terraria from Steam",
    "Vintage Story": "Launches Native or Flatpak version",
    "Luanti": "Launches Native or Flatpak version",
    "ClassiCube": "Launches Native ClassiCube"
}

def load_config():
    cfg = DEFAULTS.copy()
    if os.path.exists(CONFIG_FILE):
        user_cfg = json.load(open(CONFIG_FILE))
        for key, val in user_cfg.items():
            if key in GAMES:
                if "server_panel" in user_cfg.get(key, {}):
                    user_cfg[key]["server_type"] = "web"
                    user_cfg[key]["server_exec"] = user_cfg[key].pop("server_panel")
                elif "server_manager" in user_cfg.get(key, {}):
                    user_cfg[key]["server_type"] = "app"
                    user_cfg[key]["server_exec"] = user_cfg[key].pop("server_manager")
                elif "server_exec" not in user_cfg.get(key, {}):
                    user_cfg[key]["server_type"] = "none"
                    user_cfg[key]["server_exec"] = ""

                cfg.setdefault(key, {})
                cfg[key].update(val)
            elif key == "update_check":
                cfg["update_check"] = val
    return cfg

def save_config(cfg):
    with open(CONFIG_FILE, "w") as f:
        json.dump(cfg, f, indent=2)

class SettingsDialog(QDialog):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle("Settings")
        self.setFixedSize(800, 540)
        self.config = load_config()
        self.edits = {}
        self.init_ui()

    def init_ui(self):
        scroll = QScrollArea(self)
        scroll.setWidgetResizable(True)
        inner = QWidget()
        layout = QVBoxLayout(inner)
        scroll.setWidget(inner)

        outer_layout = QVBoxLayout(self)
        outer_layout.addWidget(scroll)

        games_config_label = QLabel("Games Config:")
        games_config_label.setObjectName("SettingsLabel")
        games_config_label.setWordWrap(True)
        layout.addWidget(games_config_label)

        info_label = QLabel(
            'Read the <a href="https://github.com/AndusDEV/Cuberry/blob/master/README.md#how-to-configure-the-editions">project\'s README on GitHub</a> \
            to learn how to configure the launcher.'
            )
        info_label.setOpenExternalLinks(True)
        info_label.setWordWrap(True)
        layout.addWidget(info_label)

        for game in GAMES:
            cfg = self.config.get(game, {})
            box = QGroupBox(game)
            box_layout = QVBoxLayout(box)

            description_label = QLabel(DESCRIPTIONS.get(game, ""))
            description_label.setWordWrap(True)
            description_label.setObjectName("SettingsDescriptionLabel")
            box_layout.addWidget(description_label)

            # Show checkbox
            show_cb = QCheckBox("Show in launcher")
            show_cb.setChecked(cfg.get("show", False))
            box_layout.addWidget(show_cb)
            self.edits[(game, "show")] = show_cb

            # Launcher type (only for MC: Java, MC: Bedrock, Vintage Story, Luanti)
            if game in ["Minecraft: Java Edition", "Minecraft: Bedrock Edition", "Vintage Story", "Luanti"]:
                rb_native, rb_flatpak = QRadioButton("Native"), QRadioButton("Flatpak")
                bg = QButtonGroup(self)
                bg.addButton(rb_native); bg.addButton(rb_flatpak)
                (rb_flatpak if cfg.get("type") == "flatpak" else rb_native).setChecked(True)

                row = QHBoxLayout()
                row.addWidget(QLabel("Launcher Type:"))
                row.addWidget(rb_native)
                row.addWidget(rb_flatpak)
                box_layout.addLayout(row)
                self.edits[(game, "type")] = bg
            
            # Game version (only for MC: Story Mode 1/2)
            if game in ["Minecraft: Story Mode", "Minecraft Story Mode: Season 2"]:
                rb_steam, rb_lutris = QRadioButton("Steam"), QRadioButton("Lutris (GOG)")
                bg = QButtonGroup(self)
                bg.addButton(rb_steam); bg.addButton(rb_lutris)
                (rb_lutris if cfg.get("version") == "lutris" else rb_steam).setChecked(True)
                
                row = QHBoxLayout()
                row.addWidget(QLabel("Game Version:"))
                row.addWidget(rb_steam)
                row.addWidget(rb_lutris)
                box_layout.addLayout(row)
                self.edits[(game, "version")] = bg

            # Exec path
            if "exec_path" in cfg:
                le = QLineEdit(cfg.get("exec_path", ""))
                btn = QPushButton("Browse")
                btn.clicked.connect(lambda _, le=le: self._browse(le, QFileDialog.getOpenFileName))
                row = QHBoxLayout()
                row.addWidget(QLabel("Executable:"))
                row.addWidget(le)
                row.addWidget(btn)
                box_layout.addLayout(row)
                self.edits[(game, "exec_path")] = le

            # Instances path (MC: Java only)
            if game == "Minecraft: Java Edition":
                le = QLineEdit(cfg.get("instances_path", ""))
                btn = QPushButton("Browse")
                btn.clicked.connect(lambda _, le=le: self._browse(le, QFileDialog.getExistingDirectory))
                row = QHBoxLayout()
                row.addWidget(QLabel("Instances Path:"))
                row.addWidget(le)
                row.addWidget(btn)
                box_layout.addLayout(row)
                self.edits[(game, "instances_path")] = le

            # ROM path (Emulator only)
            if game == "Minecraft: Xbox 360 Edition":
                le = QLineEdit(cfg.get("rom_path", ""))
                btn = QPushButton("Browse")
                btn.clicked.connect(lambda _, le=le: self._browse(le, QFileDialog.getExistingDirectory))
                row = QHBoxLayout()
                row.addWidget(QLabel("ROM Path:"))
                row.addWidget(le)
                row.addWidget(btn)
                box_layout.addLayout(row)
                self.edits[(game, "rom_path")] = le
            
            # Server support (for select games only)
            if game in ["Minecraft: Java Edition", "Minecraft: Bedrock Edition", "Terraria", "Vintage Story", "Luanti", "ClassiCube"]:
                server_box = QGroupBox("Server Settings")
                server_layout = QVBoxLayout(server_box)

                rb_none, rb_web, rb_app = QRadioButton("None"), QRadioButton("Web Panel (URL)"), QRadioButton("Manager App (Executable)")
                bg = QButtonGroup(self)
                bg.addButton(rb_none); bg.addButton(rb_web); bg.addButton(rb_app)

                server_type = cfg.get("server_type", "none")
                if server_type == "web":
                    rb_web.setChecked(True)
                elif server_type == "app":
                    rb_app.setChecked(True)
                else:
                    rb_none.setChecked(True)

                row = QHBoxLayout()
                row.addWidget(QLabel("Server Type:"))
                row.addWidget(rb_none)
                row.addWidget(rb_web)
                row.addWidget(rb_app)
                server_layout.addLayout(row)

                self.edits[(game, "server_type")] = bg

                le = QLineEdit(cfg.get("server_exec", ""))
                browse_btn = QPushButton("Browse")
                browse_btn.setEnabled(server_type == "app")
                browse_btn.clicked.connect(lambda _, le=le: self._browse(le, QFileDialog.getOpenFileName))

                input_row = QHBoxLayout()
                input_row.addWidget(QLabel("Path or URL:"))
                input_row.addWidget(le)
                input_row.addWidget(browse_btn)
                server_layout.addLayout(input_row)

                self.edits[(game, "server_exec")] = le

                box_layout.addWidget(server_box)

            layout.addWidget(box)

        layout.addItem(QSpacerItem(20, 20, QSizePolicy.Minimum, QSizePolicy.Expanding))

        cuberry_settings_label = QLabel("Cuberry Settings:")
        cuberry_settings_label.setObjectName("SettingsLabel")
        cuberry_settings_label.setWordWrap(True)
        layout.addWidget(cuberry_settings_label)

        self.update_check = QCheckBox("Check For Updates On Start")
        self.update_check.setChecked(self.config.get("update_check", True))
        layout.addWidget(self.update_check)

        theme_label = QLabel("Theme:")
        layout.addWidget(theme_label)

        theme_files = [f[:-4] for f in os.listdir("assets/ui/themes") if f.endswith(".qss")]
        self.theme_selector = QComboBox()
        self.theme_selector.setStyleSheet("""
            QComboBox {
                padding: 4px;
                min-height: 24px;
                font-size: 12px;
            }
            QComboBox::drop-down {
                width: 24px;
            }
            QComboBox::down-arrow {
                width: 10px;
                height: 10px;
            }
        """)
        self.theme_selector.addItems(theme_files)

        try:
            with open("theme.txt", "r") as f:
                current_theme = f.read().strip()
                index = self.theme_selector.findText(current_theme)
                if index != -1:
                    self.theme_selector.setCurrentIndex(index)
        except:
            pass

        layout.addWidget(self.theme_selector)

        github_label = QLabel('<a href="https://github.com/AndusDEV/Cuberry">Cuberry GitHub Repo</a>')
        github_label.setOpenExternalLinks(True)
        github_label.setWordWrap(True)
        layout.addWidget(github_label)

        version_label = QLabel(f"Launcher Version: <strong>{__version__}</strong>")
        version_label.setWordWrap(True)
        layout.addWidget(version_label)

        btn_row = QHBoxLayout()
        btn_save, btn_cancel = QPushButton("Save"), QPushButton("Cancel")
        btn_save.clicked.connect(self.on_save)
        btn_cancel.clicked.connect(self.reject)
        btn_row.addStretch(); btn_row.addWidget(btn_save); btn_row.addWidget(btn_cancel)
        outer_layout.addLayout(btn_row)

    def _browse(self, lineedit, func):
        result = func(self, "Select")[0] if func == QFileDialog.getOpenFileName else func(self, "Select")
        if result:
            lineedit.setText(result)

    def on_save(self):
        for (game, key), widget in self.edits.items():
            if key == "show":
                val = widget.isChecked()
            elif key == "type":
                val = "flatpak" if widget.buttons()[1].isChecked() else "native"
            elif key == "version":
                val = "lutris" if widget.buttons()[1].isChecked() else "steam"
            elif key == "server_type":
                continue 
            elif key == "server_exec":
                continue 
            else:
                val = widget.text().strip()
            self.config.setdefault(game, {})[key] = val

        for game in GAMES:
            if (game, "server_type") in self.edits and (game, "server_exec") in self.edits:
                bg = self.edits[(game, "server_type")]
                server_path = self.edits[(game, "server_exec")].text().strip()
                
                server_type = "none"
                if bg.buttons()[1].isChecked():
                    server_type = "web"
                elif bg.buttons()[2].isChecked():
                    server_type = "app"
                
                self.config[game]["server_type"] = server_type
                if server_type != "none":
                    self.config[game]["server_exec"] = server_path
                else:
                    self.config[game]["server_exec"] = ""

        self.config["update_check"] = self.update_check.isChecked()

        try:
            save_config(self.config)
            QMessageBox.information(self, "Saved", "Configuration saved."
                                                   "\nRestart the launcher to load the new changes.")
            self.accept()
        except Exception as e:
            QMessageBox.critical(self, "Error", str(e))

        selected_theme = self.theme_selector.currentText()
        try:
            with open("theme.txt", "w") as f:
                f.write(selected_theme)
        except Exception as e:
            QMessageBox.critical(self, "Error", f"Failed to save theme: {e}")