"""Studio login window (PySide6).

Lists every active user from the local store, lets the operator pick
themselves and enter their PIN. On success, populates the global
:class:`SessionHolder` and emits :pyattr:`logged_in`.
"""

from __future__ import annotations

from PySide6.QtCore import Qt, Signal
from PySide6.QtWidgets import (
    QComboBox,
    QDialog,
    QDialogButtonBox,
    QFormLayout,
    QLabel,
    QLineEdit,
    QMessageBox,
    QVBoxLayout,
)

from arautopilot.core.audit import AuditEvent, AuditLog, AuditOutcome
from arautopilot.core.user_store import UserStore
from arautopilot.studio.session import Session, SessionHolder


class LoginDialog(QDialog):
    """Modal login dialog. Emits :pyattr:`logged_in(session)` on success."""

    logged_in = Signal(object)  # Session

    def __init__(
        self,
        store: UserStore,
        audit: AuditLog,
        parent: object | None = None,
    ) -> None:
        super().__init__(parent)
        self._store = store
        self._audit = audit
        self.setWindowTitle("AR-Autopilot Studio -- Login")
        self.setModal(True)
        self.setMinimumWidth(360)

        layout = QVBoxLayout(self)
        intro = QLabel("Select your user and enter the PIN.")
        intro.setWordWrap(True)
        layout.addWidget(intro)

        form = QFormLayout()
        self._user_combo = QComboBox()
        for user in self._store.all_users():
            if not user.active:
                continue
            self._user_combo.addItem(
                f"{user.display_name}  --  {user.role.value}",
                userData=user.user_id,
            )
        form.addRow("User:", self._user_combo)

        self._pin_field = QLineEdit()
        self._pin_field.setEchoMode(QLineEdit.EchoMode.Password)
        self._pin_field.setMaxLength(8)
        self._pin_field.setPlaceholderText("4-8 digits")
        self._pin_field.setInputMethodHints(Qt.InputMethodHint.ImhDigitsOnly)
        form.addRow("PIN:", self._pin_field)
        layout.addLayout(form)

        buttons = QDialogButtonBox(
            QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel
        )
        buttons.accepted.connect(self._try_login)
        buttons.rejected.connect(self.reject)
        layout.addWidget(buttons)

        if self._user_combo.count() == 0:
            QMessageBox.critical(
                self,
                "No users available",
                "The local user store is empty. Run the demo seed:\n\n"
                "    python -m arautopilot.studio.app --seed-demo",
            )

    # ----- Internal -------------------------------------------------------
    def _try_login(self) -> None:
        user_id = self._user_combo.currentData()
        pin = self._pin_field.text()
        user = self._store.get(user_id) if user_id else None
        if user is None:
            QMessageBox.warning(self, "Login", "Pick a user.")
            return
        if not user.active:
            QMessageBox.warning(self, "Login", "This user is disabled.")
            return
        if not user.verify_pin(pin):
            self._audit.append(
                AuditEvent(
                    user_id=user.user_id,
                    role=user.role.value,
                    action="login",
                    outcome=AuditOutcome.DENIED,
                    reason="bad PIN",
                )
            )
            QMessageBox.warning(self, "Login", "Incorrect PIN.")
            self._pin_field.clear()
            self._pin_field.setFocus()
            return

        touched = user.touch_login()
        self._store.replace(touched)
        self._audit.append(
            AuditEvent(
                user_id=touched.user_id,
                role=touched.role.value,
                action="login",
                outcome=AuditOutcome.SUCCESS,
            )
        )
        session = Session(user=touched, store=self._store, audit=self._audit)
        SessionHolder.set(session)
        self.logged_in.emit(session)
        self.accept()
