import webbrowser
from sys import platform
from os import environ

from PySide6 import QtGui
from PySide6.QtCore import Qt, QTimer
from PySide6.QtUiTools import QUiLoader
from PySide6.QtWidgets import QMainWindow, QSizePolicy
from PySide6.QtCore import QThread, Signal

from config.config_manager import ConfigManager
from config.constants import PlayerServerInfo, Urls
from tools.http_client import ApiError
from ui.error_dialog import show_qt_error
from ui.hazard_stripes import HazardButton
from controllers.audio_controller import AudioController
from controllers.glow_animator import GlowAnimator
from controllers.window_dragger import WindowDragger
from discord import discord_oauth
from fivemserver.whitelistmanager import WhiteList
from fivemserver.fivemlauncher import FiveMLauncher
from fivemserver.queuemanager import QueueManager
from fivemserver.get_server_token import GetServerTokenForDiscord
from fake_patch_notes import patch_note

# For Linux Wayland to authorize moving window
if platform.startswith('linux'):
   environ["QT_QPA_PLATFORM"] = "xcb"

class MainWindow(QMainWindow):
    #update = Signal(str)  # Reçoit les callbacks de QueueManager

    def __init__(self, bundle_dir: str, config_manager: ConfigManager):
        super().__init__()

        self.config = config_manager
        self.stored_user_id = self.config.get_discord_user()
        self.queue_thread = None
        self.queue_position_value = None
        self.close_timer = None
        self.countdown_timer = None
        self.remaining_time = 0  # en secondes

        # UI
        self.ui = QUiLoader().load(f"{bundle_dir}/ui/mainwindow_vertical_pager.ui", self)
        self.setCentralWidget(self.ui.centralWidget())
        self.setWindowFlags(Qt.WindowType.FramelessWindowHint | Qt.WindowType.Window)
        self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)

        # Par défaut on affiche la page normal pour la connexion au serveur
        self.ui.stackedWidget.setCurrentIndex(0)
        # On cache par défaut les infos liste d'attente
        self.ui.queue_lbl.hide()
        self.ui.queue_position.hide()


        # Si l'id discord = "" ou des espace, alors on affiche la page comme quoi faut être connecté à discord.
        if self.stored_user_id == "" or self.stored_user_id.isspace():
            self.ui.stackedWidget.setCurrentIndex(1)
        else:
            try:
                # on vérifie si le joueur est whitelisté
                WhiteList.check_whitelist(Urls.API_URL.value, self.stored_user_id)
            except ApiError as exc:
                show_qt_error(self, "La Tanière", f"Impossible de vérifier la whitelist.\n\n{exc}")
                PlayerServerInfo.is_whitelist = False
                PlayerServerInfo.is_staff = False

            # si on est whitelisté, on démarre la file d'attente
            if PlayerServerInfo.is_whitelist:
                self.start_queue()
                self.ui.queue_lbl.show()
                self.ui.queue_position.show()
            else:
                self.ui.stackedWidget.setCurrentIndex(2)

        # Test bouton en contruction
        en_chantier = False
        # on set la css du bouton en fonction de la valeur de la variable en_chantier
        self.set_en_chantier(en_chantier)
        if en_chantier:
            old_btn = self.ui.connexion_btn
            parent_layout = self.ui.verticalLayout_6  # layout direct du bouton dans le .ui

            index = parent_layout.indexOf(old_btn)

            new_btn = HazardButton(old_btn.parentWidget())
            new_btn.setObjectName("connexion_btn")
            new_btn.setText("EN MAINTENANCE")
            new_btn.setIcon(old_btn.icon())
            new_btn.setIconSize(old_btn.iconSize())
            new_btn.setMinimumSize(old_btn.minimumSize())
            new_btn.set_hazard(True)

            parent_layout.takeAt(index)
            old_btn.deleteLater()
            parent_layout.insertWidget(index, new_btn)

            self.ui.connexion_btn = new_btn
            self.ui.connexion_btn.clicked.connect(self._on_connexion)

        # centrage vertical du bouton connexion
        if not PlayerServerInfo.is_staff:
            self.ui.staff_btn.hide()
            layout = self.ui.verticalLayout_6
            # Trouver et modifier le spacer item
            for i in range(layout.count()):
                item = layout.itemAt(i)
                if item.spacerItem():  # C'est un spacer
                    item.spacerItem().changeSize(20, 15, QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed)
                    layout.invalidate()  # Forcer le recalcul du layout
                    break

        self.ui.info_text.setMarkdown(patch_note)

        # Sous-systèmes
        self._audio   = AudioController(self.config, self.ui.audio_volume_adjust, self.ui.mute_btn)
        self._glow    = GlowAnimator(self.ui.connexion_btn)
        self._dragger = WindowDragger(self)

        self._connect_signals()
        self._center_window()

        self.show()


    # ------------------------------------------------------------------
    # Setup
    # ------------------------------------------------------------------

    def _connect_signals(self) -> None:
        self.ui.close_btn.clicked.connect(self.close)
        self.ui.minimize_btn.clicked.connect(self.showMinimized)
        self.ui.connexion_btn.clicked.connect(self._on_connexion)
        self.ui.discord_btn.clicked.connect(self._on_discord)
        self.ui.intranet_btn.clicked.connect(self._on_intranet)
        self.ui.discord_auth_btn.clicked.connect(self._on_discord_auth_btn)
        self.ui.no_whitelist_btn.clicked.connect(self.close)

    def _center_window(self) -> None:
        self.adjustSize()
        screen = (
            QtGui.QGuiApplication.screenAt(QtGui.QCursor.pos())
            or QtGui.QGuiApplication.primaryScreen()
        )
        rect = self.frameGeometry()
        rect.moveCenter(screen.availableGeometry().center())
        self.move(rect.topLeft())

    # ------------------------------------------------------------------
    # Button handlers
    # ------------------------------------------------------------------

    def _on_connexion(self) -> None:
        try:
            if not self.stored_user_id or self.stored_user_id.isspace():
                show_qt_error(
                    self,
                    "Connexion impossible",
                    "Aucun identifiant Discord n'est disponible. Merci de passer par la connexion Discord."
                )
                return

            if not PlayerServerInfo.session_id:
                PlayerServerInfo.session_id = GetServerTokenForDiscord.authenticate(Urls.API_URL.value)
                GetServerTokenForDiscord.register_discord_user(
                    self.stored_user_id,
                    PlayerServerInfo.session_id,
                )

            if self.queue_position_value is None:
                show_qt_error(
                    self,
                    "Connexion en attente",
                    "La position dans la file d'attente n'est pas encore connue."
                )
                return

            if self.queue_position_value != 0:
                show_qt_error(
                    self,
                    "Connexion en attente",
                    f"Tu dois attendre ton tour.\n\nPosition actuelle : {self.queue_position_value}"
                )
                return

            FiveMLauncher.launch()
            # on disable le bouton connexion une fois fivem lancé.
            self.ui.connexion_btn.setEnabled(False)

            # fermer l'application après 60 secondes (60000 ms)
            self.schedule_close()


        except ApiError as exc:
            show_qt_error(self, "Connexion impossible", f"Erreur lors de la connexion.\n\n{exc}")

    @staticmethod
    def _on_discord() -> None:
        webbrowser.open(Urls.DISCORD.value)

    def _on_intranet(self) -> None:
        webbrowser.open(Urls.INTRANET.value)
        self._glow.start()

    def _on_discord_auth_btn(self) -> None:
        try:
            test = discord_oauth.get_discord_user_id()
            self.config.set_discord_user(test[0])
            PlayerServerInfo.session_id = test[1]
            self.config.save()
            self.ui.stackedWidget.setCurrentIndex(0)
        except ApiError as exc:
            show_qt_error(self, "Connexion Discord", f"Impossible de récupérer ton compte Discord.\n\n{exc}")
    # ------------------------------------------------------------------
    # Mouse events → délégués au WindowDragger
    # ------------------------------------------------------------------

    def mousePressEvent(self, event: QtGui.QMouseEvent) -> None:
        self._dragger.mouse_press(event)
        super().mousePressEvent(event)

    def mouseMoveEvent(self, event: QtGui.QMouseEvent) -> None:
        self._dragger.mouse_move(event)
        super().mouseMoveEvent(event)

    def mouseReleaseEvent(self, event: QtGui.QMouseEvent) -> None:
        self._dragger.mouse_release(event)
        super().mouseReleaseEvent(event)

    # ------------------------------------------------------------------
    # Close
    # ------------------------------------------------------------------

    def closeEvent(self, event) -> None:
        if self.queue_thread and self.queue_thread.isRunning():
            self.queue_thread.stop()
            self.queue_thread.wait()  # Attend que le thread se termine proprement
        self.config.save()
        super().closeEvent(event)

    # ------------------------------------------------------------------
    # Change ui on runtime
    # ------------------------------------------------------------------
    def set_en_chantier(self, valeur: bool):
        self.en_chantier = valeur  # ta variable Python
        self.ui.connexion_btn.setProperty("en_chantier", valeur)  # propriété Qt
        self.ui.connexion_btn.style().unpolish(self.ui.connexion_btn)
        self.ui.connexion_btn.style().polish(self.ui.connexion_btn)

    # ------------------------------------------------------------------
    # Schedule de fermeture du launcher
    # ------------------------------------------------------------------
    def schedule_close(self, delay: int = 60000):
        # Normalisation du délai
        if not isinstance(delay, int) or delay <= 0:
            delay = 60000

        # Conversion en secondes
        self.remaining_time = delay // 1000

        # 🔁 Annule les timers existants
        if self.close_timer:
            self.close_timer.stop()
            self.close_timer.deleteLater()

        if self.countdown_timer:
            self.countdown_timer.stop()
            self.countdown_timer.deleteLater()

        # ⏱ Timer de fermeture
        self.close_timer = QTimer(self)
        self.close_timer.setSingleShot(True)
        self.close_timer.timeout.connect(self.close)
        self.close_timer.start(delay)

        # ⏳ Timer de countdown (1 seconde)
        self.countdown_timer = QTimer(self)
        self.countdown_timer.timeout.connect(self._update_countdown)
        self.countdown_timer.start(1000)

        # Affichage initial
        self._update_countdown()

    # on affiche un compteur avant fermeture automatique
    def _update_countdown(self):
        if self.remaining_time <= 0:
            if self.countdown_timer:
                self.countdown_timer.stop()
            return

        minutes = self.remaining_time // 60
        seconds = self.remaining_time % 60
        self.ui.queue_lbl.setText(f"⏳ Fermeture dans {minutes:02d}:{seconds:02d}")

        self.remaining_time -= 1

    # ------------------------------------------------------------------
    # Queue managment
    # ------------------------------------------------------------------
    def start_queue(self):
        self.queue_thread = QueueThread(self.stored_user_id)
        self.queue_thread = QueueThread(self.stored_user_id, parent=self)  # ← parent=self
        self.queue_thread.update.connect(self.handle_update)
        self.queue_thread.start()

        # 🧪 TEMP - Simule une position en queue pour tester l'UI
        # self.handle_update("position:3:10")

    def handle_update(self, message: str):
        if message == "ok":
            self.ui.queue_lbl.setVisible(True)
            self.ui.queue_position.setVisible(False)
            self.ui.queue_lbl.setText("🚀 C'est votre tour !")
            self.queue_position_value = 0

        elif message == "ready":
            self.ui.queue_lbl.setVisible(True)
            self.ui.queue_position.setVisible(False)
            self.ui.queue_lbl.setText("🚀 C'est votre tour !")
            self.queue_position_value = 0

        elif message.startswith("position:"):
            _, pos, total = message.split(":")
            self.queue_position_value = int(pos)
            self.ui.queue_lbl.setVisible(True)
            self.ui.queue_position.setVisible(True)
            self.ui.queue_position.setText(f"{pos}")

    def launch_fivem(self):
        pass

class QueueThread(QThread):
    update = Signal(str)

    def __init__(self, user_id: str, parent=None):  # ← parent=None
        super().__init__(parent)  # ← passé à QThread
        self.manager = QueueManager(
            user_id=user_id,
            on_update=self.update.emit
        )

    def run(self):
        self.manager.start()

    def stop(self):
        self.manager.stop()
