# -*- coding: utf-8 -*-
# gui/login_dialog.py

"""Модальный диалог авторизации пользователя в составе Dispatch.

Назначение модуля:
    Локальная копия диалога авторизации USMS, обращённая к сервису
    `hub.my_account.auth_service` независимого приложения Dispatch.
    Источник учётных данных — каталог `DB_dispatch`.

Архитектурные ограничения:
    - QSS подключается только через реестр `APP_STYLES`, без inline-стилей.
    - Все элементы построены через канонические обёртки `Button`,
      `Dialog`, `Label`, `SContainer`, `VContainer`, `HContainer`.
    - Локальные процентные доли элементов вычислены вручную, без
      хелперов layout.
"""

from __future__ import annotations

from PySide6.QtCore import Qt, Slot
from PySide6.QtWidgets import QLineEdit, QPushButton

from gui.components import Button, Dialog, Label
from gui.containers import HContainer, SContainer, VContainer
from gui.styles import APP_STYLES
from gui.theme_bus import theme_bus


class LoginDialog(Dialog):
    """Диалог входа: два поля (логин / пароль), кнопки Отмена / Войти."""

    def __init__(self, parent=None):
        self._login_input: QLineEdit | None = None
        self._password_input: QLineEdit | None = None
        self._login_container: SContainer | None = None
        self._password_container: SContainer | None = None
        self._login_error_label: Label | None = None
        self._password_error_label: Label | None = None
        self._cancel_button: Button | None = None
        self._submit_button: Button | None = None
        self._theme: str = "dark"

        super().__init__(
            title="Авторизация",
            width=400,
            height=340,
            modal=True,
            parent=parent,
        )
        self._theme = "dark" if self.palette().window().color().lightness() < 128 else "light"
        self._setup_ui()
        self._connect_signals()
        for pb in self.findChildren(QPushButton):
            pb.setAutoDefault(False)
            pb.setDefault(False)
        self._apply_theme(self._theme)

    # ── UI assembly ──────────────────────────────────────────────

    def _setup_ui(self) -> None:
        root = VContainer(margin=[28, 8, 28, 24], spacing=0)
        self.add_widget(root)

        root.add_widget(self._build_title())
        root.add_widget(self._build_login_field())
        root.add_widget(self._build_password_field())
        root.add_widget(self._build_actions())

    def _build_title(self) -> Label:
        return Label(
            "Вход в систему",
            height_percent=14,
            style="LOGIN_TITLE",
        )

    def _build_login_field(self) -> SContainer:
        field = SContainer(
            height_percent=24,
            spacing=2,
            orientation="v",
            content_fit=False,
        )

        field.add_widget(Label(
            "Логин",
            height_percent=28,
            style="LOGIN_FIELD_LABEL",
        ))

        self._login_container = SContainer(
            height_percent=42,
            orientation="h",
            content_fit=False,
        )
        self._login_input = QLineEdit()
        self._login_input.setPlaceholderText("Введите логин")
        self._login_container.add_widget(self._login_input)
        field.add_widget(self._login_container)

        self._login_error_label = Label(
            "",
            height_percent=24,
            style="LOGIN_ERROR_LABEL",
        )
        self._login_error_label.set_visible(False)
        field.add_widget(self._login_error_label)

        return field

    def _build_password_field(self) -> SContainer:
        field = SContainer(
            height_percent=24,
            spacing=2,
            orientation="v",
            content_fit=False,
        )

        field.add_widget(Label(
            "Пароль",
            height_percent=28,
            style="LOGIN_FIELD_LABEL",
        ))

        self._password_container = SContainer(
            height_percent=42,
            orientation="h",
            content_fit=False,
        )
        self._password_input = QLineEdit()
        self._password_input.setPlaceholderText("Введите пароль")
        self._password_input.setEchoMode(QLineEdit.EchoMode.Password)
        self._password_container.add_widget(self._password_input)
        field.add_widget(self._password_container)

        self._password_error_label = Label(
            "",
            height_percent=24,
            style="LOGIN_ERROR_LABEL",
        )
        self._password_error_label.set_visible(False)
        field.add_widget(self._password_error_label)

        return field

    def _build_actions(self) -> HContainer:
        actions = HContainer(
            height_percent=16,
            spacing=0,
            content_fit=False,
        )

        SContainer(width_percent=10, height_percent=100, parent=actions)

        self._cancel_button = Button(
            "Отмена",
            width_percent=26,
            height_percent=100,
            margin=0,
            style="LOGIN_CANCEL_BUTTON",
            content_fit=False,
        )
        actions.add_widget(self._cancel_button)

        SContainer(width_percent=28, height_percent=100, parent=actions)

        self._submit_button = Button(
            "Войти",
            width_percent=26,
            height_percent=100,
            margin=0,
            style="LOGIN_SUBMIT_BUTTON",
            content_fit=False,
        )
        actions.add_widget(self._submit_button)

        SContainer(width_percent=10, height_percent=100, parent=actions)
        return actions

    # ── Signals ──────────────────────────────────────────────────

    def _connect_signals(self) -> None:
        self._cancel_button.clicked.connect(self.reject)
        self._submit_button.clicked.connect(self._on_submit)
        self._login_input.returnPressed.connect(self._on_submit)
        self._password_input.returnPressed.connect(self._on_submit)
        self._login_input.textChanged.connect(self._clear_login_error)
        self._password_input.textChanged.connect(self._clear_password_error)
        theme_bus.theme_changed.connect(self._on_theme_changed)

    # ── Validation ───────────────────────────────────────────────

    def _on_submit(self) -> None:
        # Импорт локального сервиса аутентификации Dispatch.
        # Источник учётных записей — `DB_dispatch/0_users.py`.
        from auth_service import authenticate

        login = self._login_input.text().strip()
        password = self._password_input.text().strip()

        has_error = False
        if not login:
            self._show_login_error("Поле логин не может быть пустым")
            has_error = True
        if not password:
            self._show_password_error("Поле пароль не может быть пустым")
            has_error = True
        if has_error:
            return

        user, err = authenticate(login, password)
        if err == "no_user":
            self._show_login_error("Пользователь не существует")
            self._show_password_error("Пользователь не существует")
            return
        if err == "bad_password":
            self._show_password_error("Неверный пароль")
            return

        self._authenticated_user = user
        self.accept()

    def get_authenticated_user(self) -> dict | None:
        return getattr(self, "_authenticated_user", None)

    # ── Error display ────────────────────────────────────────────

    def _show_login_error(self, msg: str) -> None:
        self._login_error_label.set_text(msg)
        self._login_error_label.set_visible(True)
        self._apply_input_style(self._login_container, error=True)

    def _show_password_error(self, msg: str) -> None:
        self._password_error_label.set_text(msg)
        self._password_error_label.set_visible(True)
        self._apply_input_style(self._password_container, error=True)

    @Slot()
    def _clear_login_error(self) -> None:
        self._login_error_label.set_text("")
        self._login_error_label.set_visible(False)
        self._apply_input_style(self._login_container, error=False)

    @Slot()
    def _clear_password_error(self) -> None:
        self._password_error_label.set_text("")
        self._password_error_label.set_visible(False)
        self._apply_input_style(self._password_container, error=False)

    # ── Theming ──────────────────────────────────────────────────

    @Slot(str)
    def _on_theme_changed(self, theme: str) -> None:
        self._apply_theme(theme)

    def _apply_theme(self, theme: str) -> None:
        self._theme = theme
        suffix = "_LIGHT" if theme == "light" else "_DARK"

        dialog_qss = APP_STYLES.get(f"LOGIN_DIALOG{suffix}", "")
        self.setStyleSheet(dialog_qss)

        self._apply_input_style(self._login_container, error=False)
        self._apply_input_style(self._password_container, error=False)

    def _apply_input_style(self, container: SContainer, error: bool) -> None:
        suffix = "_LIGHT" if self._theme == "light" else "_DARK"
        key = f"LOGIN_INPUT_ERROR{suffix}" if error else f"LOGIN_INPUT{suffix}"
        qss = APP_STYLES.get(key, "")
        container.setStyleSheet(qss)
