﻿from PySide6.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QDialog, QSizePolicy
from PySide6.QtCore import QSettings, Qt, Signal
import logging

from pypos.themes.styled_widgets import StyledLabel, StyledLineEdit, StyledPushButton, StyledCheckBox
from pypos.themes.style_manager import StyleManager
from pypos.modules.auth.views.config_dialog import ConfigDialog
from pypos.modules.auth.views.master_password_dialog import MasterPasswordDialog
from pypos.modules.auth.config.auth_config import get_auth_dialog_config, get_auth_theme_name
from pypos.core.base_view import BaseView

LOGGER = logging.getLogger(__name__)


class LoginWindow(BaseView, QWidget):
    # edited by glg
    # Bridge thread-safe untuk update hasil probe network dari worker ke UI thread.
    network_gate_payload_ready = Signal(object)

    def __init__(self, controller):
        super().__init__()
        # edited by glg
        # Pastikan root widget memaint background stylesheet secara konsisten.
        self.setAttribute(Qt.WA_StyledBackground, True)
        self.controller = controller
        self.settings = QSettings("MayaGrahaKencana", "POS_System")
        self.theme = self.get_theme_from_config()
        self._network_gate_state = ""
        self._network_gate_level = "info"
        self._network_gate_blocked = False

        self.setup_ui()
        self.load_saved_credentials()
        self._apply_window_theme()

    # edited by glg
    def emit_network_gate_payload(self, payload):
        try:
            self.network_gate_payload_ready.emit(payload)
        except (RuntimeError, TypeError):
            pass

    def get_theme_from_config(self):
        try:
            return get_auth_theme_name()
        except (RuntimeError, ValueError, TypeError, OSError) as e:
            LOGGER.warning("Gagal membaca theme dari config: %s", e)
            return "default"

    def setup_ui(self):
        cfg = get_auth_dialog_config()
        # edited by glg
        # Object name untuk styling root login saja agar tidak menimpa child widget lain.
        self.setObjectName("loginWindowRoot")
        layout = QVBoxLayout()
        spacing = int(cfg.get("login_layout_spacing") or 10)
        margin = int(cfg.get("login_layout_margin") or 20)
        layout.setSpacing(spacing)
        layout.setContentsMargins(margin, margin, margin, margin)

        self.title_label = StyledLabel("Login System", self.theme)
        self.title_label.setObjectName("loginTitleLabel")
        self.title_label.setAlignment(Qt.AlignCenter)
        self._apply_title_label_style()
        layout.addWidget(self.title_label)

        # edited by glg
        self.network_status_label = StyledLabel("Memeriksa koneksi jaringan...", self.theme)
        self.network_status_label.setWordWrap(True)
        self.network_status_label.setObjectName("loginNetworkStatus")
        layout.addWidget(self.network_status_label)

        self.label_username = StyledLabel("Username:", self.theme)
        self.label_username.setObjectName("loginFieldLabelUsername")
        self.input_username = StyledLineEdit("Masukkan username Anda...", self.theme)

        self.label_password = StyledLabel("Password:", self.theme)
        self.label_password.setObjectName("loginFieldLabelPassword")
        self._apply_field_label_styles()
        password_layout = QHBoxLayout()
        password_layout.setSpacing(6)

        self.input_password = StyledLineEdit("Masukkan password Anda...", self.theme)
        self.input_password.setEchoMode(StyledLineEdit.Password)
        self.input_password.returnPressed.connect(self.check_login)

        self.toggle_password_btn = StyledPushButton("Show", self.theme, "secondary")
        # edited by glg
        # Tandai tombol compact agar tidak dipaksa min-width global oleh QSS aplikasi.
        self.toggle_password_btn.setProperty("compactButton", True)
        # edited by glg
        # Lebar minimum dinaikkan agar teks Show/Hide tidak terpotong oleh padding style.
        toggle_w = max(int(cfg.get("login_toggle_btn_width") or 40), 70)
        toggle_h = int(cfg.get("login_toggle_btn_height") or 35)
        self.toggle_password_btn.setMinimumWidth(toggle_w)
        self.toggle_password_btn.setMinimumHeight(toggle_h)
        self.toggle_password_btn.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
        self.toggle_password_btn.setToolTip("Tampilkan password")
        self.toggle_password_btn.clicked.connect(self.toggle_password_visibility)
        self.password_visible = False

        password_layout.addWidget(self.input_password)
        password_layout.addWidget(self.toggle_password_btn)

        # edited by glg
        # Hardening: aplikasi hanya boleh menyimpan username, bukan password plaintext.
        self.remember_me = StyledCheckBox("Ingat username", self.theme)

        self.button_login = StyledPushButton("Login", self.theme, "primary")
        self.button_login.clicked.connect(self.check_login)

        self.button_config = StyledPushButton("Config", self.theme, "secondary")
        self.button_config.clicked.connect(self.open_config)

        layout.addWidget(self.label_username)
        layout.addWidget(self.input_username)
        layout.addWidget(self.label_password)
        layout.addLayout(password_layout)
        layout.addWidget(self.remember_me)
        layout.addWidget(self.button_login)
        layout.addWidget(self.button_config)
        layout.addStretch()

        # edited by glg
        # Bungkus form login ke card agar visual hierarki jelas dan konsisten.
        self.form_card = QWidget(self)
        self.form_card.setObjectName("loginFormCard")
        self.form_card.setLayout(layout)

        root_layout = QVBoxLayout()
        root_layout.setContentsMargins(12, 12, 12, 12)
        root_layout.setSpacing(0)
        root_layout.addStretch(1)
        root_layout.addWidget(self.form_card)
        root_layout.addStretch(1)
        self.setLayout(root_layout)
        self.set_window_properties()
        self.update_network_gate(
            message="Memeriksa koneksi jaringan...",
            level="info",
            state="INIT",
            blocked=False,
        )

    def set_window_properties(self):
        cfg = get_auth_dialog_config()
        client_name = cfg.get("client_name", "")
        title = f"Login - {client_name}" if client_name else "Login System"
        self.setWindowTitle(title)

    # edited by glg
    def _apply_title_label_style(self):
        if not hasattr(self, "title_label") or self.title_label is None:
            return
        self.title_label.setStyleSheet(
            "QLabel#loginTitleLabel {"
            "font-size: 18px;"
            "font-weight: bold;"
            "color: #1f2d3d;"
            "padding: 4px 0px 6px 0px;"
            "margin: 0px;"
            "background: transparent;"
            "border: none;"
            "}"
        )

    # edited by glg
    def _apply_field_label_styles(self):
        if hasattr(self, "label_username") and self.label_username is not None:
            self.label_username.setStyleSheet(
                "QLabel#loginFieldLabelUsername {"
                "font-size: 14px;"
                "font-weight: 600;"
                "color: #1f2d3d;"
                "padding: 0px;"
                "margin: 2px 0px 0px 0px;"
                "background: transparent;"
                "border: none;"
                "}"
            )
        if hasattr(self, "label_password") and self.label_password is not None:
            self.label_password.setStyleSheet(
                "QLabel#loginFieldLabelPassword {"
                "font-size: 14px;"
                "font-weight: 600;"
                "color: #1f2d3d;"
                "padding: 0px;"
                "margin: 2px 0px 0px 0px;"
                "background: transparent;"
                "border: none;"
                "}"
            )

    # edited by glg
    def _apply_window_theme(self):
        colors = StyleManager.THEMES.get(self.theme, StyleManager.THEMES.get("default", {}))
        card_bg = str(colors.get("background") or "#ffffff")
        root_bg = "#edf1f5" if self.theme == "default" else card_bg
        text = str(colors.get("text") or "#1f2d3d")
        border = "#d4dde8" if self.theme == "default" else "#3c4652"
        self.setStyleSheet(
            "QWidget#loginWindowRoot {"
            f"background-color: {root_bg};"
            f"color: {text};"
            "}"
            "QWidget#loginFormCard {"
            f"background-color: {card_bg};"
            f"border: 1px solid {border};"
            "border-radius: 10px;"
            "padding: 6px;"
            "}"
        )

    def toggle_password_visibility(self):
        self.password_visible = not self.password_visible
        if self.password_visible:
            self.input_password.setEchoMode(StyledLineEdit.Normal)
            self.toggle_password_btn.setText("Hide")
            self.toggle_password_btn.setToolTip("Sembunyikan password")
            return
        self.input_password.setEchoMode(StyledLineEdit.Password)
        self.toggle_password_btn.setText("Show")
        self.toggle_password_btn.setToolTip("Tampilkan password")

    def load_saved_credentials(self):
        saved_username = self.settings.value("login/username", "")
        remember_me = self.settings.value("login/remember_me", False, type=bool)
        # edited by glg
        # Bersihkan key legacy password plaintext agar tidak dipakai lagi.
        legacy_saved_password = self.settings.value("login/password", "")
        if str(legacy_saved_password or "").strip():
            self.settings.remove("login/password")

        if saved_username:
            self.input_username.setText(saved_username)

        if saved_username and remember_me:
            self.remember_me.setChecked(True)

    def save_credentials(self):
        if self.remember_me.isChecked():
            # edited by glg
            # Simpan hanya username. Password tetap volatile di memori runtime.
            self.settings.setValue("login/username", self.input_username.text())
            self.settings.remove("login/password")
            self.settings.setValue("login/remember_me", True)
            return
        self.clear_saved_credentials()

    def clear_saved_credentials(self):
        self.settings.remove("login/username")
        self.settings.remove("login/password")
        self.settings.remove("login/remember_me")

    def check_login(self):
        if hasattr(self, "button_login") and not self.button_login.isEnabled():
            self.show_warning(
                "Koneksi Diperlukan",
                "Aplikasi harus online untuk melanjutkan login.",
            )
            return
        username = self.input_username.text().strip()
        password = self.input_password.text()
        if username and password:
            self.save_credentials()
        elif not self.remember_me.isChecked():
            self.clear_saved_credentials()
        if self.controller and hasattr(self.controller, "proses_login"):
            self.controller.proses_login(username, password)

    # edited by glg
    def set_login_enabled(self, enabled):
        if hasattr(self, "button_login") and self.button_login:
            self.button_login.setEnabled(bool(enabled))

    # edited by glg
    @staticmethod
    def _build_network_label_style(level, blocked):
        safe_level = str(level or "").strip().lower()
        if blocked:
            bg = "#fdecea"
            border = "#e57373"
            text = "#8e1c1c"
        elif safe_level == "success":
            bg = "#eaf7ee"
            border = "#67b37a"
            text = "#1f5d2f"
        elif safe_level == "warning":
            bg = "#fff6e5"
            border = "#f0b255"
            text = "#7a4b08"
        else:
            bg = "#eaf2fb"
            border = "#87a8d8"
            text = "#24456b"
        return (
            "QLabel#loginNetworkStatus {"
            f"background-color: {bg};"
            f"border: 1px solid {border};"
            "border-radius: 4px;"
            "padding: 6px 8px;"
            f"color: {text};"
            "font-size: 11px;"
            "}"
        )

    # edited by glg
    def update_network_gate(self, message, level="info", state="", blocked=False):
        self._network_gate_state = str(state or "").strip()
        self._network_gate_level = str(level or "info")
        self._network_gate_blocked = bool(blocked)
        text = str(message or "").strip() or "Status jaringan belum tersedia."
        if self._network_gate_state:
            text = f"[{self._network_gate_state}] {text}"
        if hasattr(self, "network_status_label") and self.network_status_label:
            self.network_status_label.setStyleSheet(
                self._build_network_label_style(level=level, blocked=blocked)
            )
            self.network_status_label.setText(text)

    def clear_fields(self):
        if not self.remember_me.isChecked():
            self.input_username.clear()
            self.input_password.clear()
        self.input_username.setFocus()

    def open_config(self):
        pwd_dialog = MasterPasswordDialog(self)
        if pwd_dialog.exec() == QDialog.Accepted:
            dlg = ConfigDialog(self)
            if dlg.exec() == QDialog.Accepted:
                if self.controller and hasattr(self.controller, "app"):
                    from pypos.core.utils.config_utils import reload_config

                    self.controller.app.config = reload_config()
                self.set_window_properties()
                if self.controller and hasattr(self.controller, "refresh_network_policy_now"):
                    self.controller.refresh_network_policy_now(
                        source="config_changed",
                        force_probe=True,
                    )

                new_theme = self.get_theme_from_config()
                if new_theme != self.theme:
                    self.theme = new_theme
                    self.update_theme()

    def update_theme(self):
        self._apply_window_theme()
        self.label_username.set_style(self.theme)
        self.input_username.set_style(self.theme)
        self.label_password.set_style(self.theme)
        self._apply_field_label_styles()
        self.input_password.set_style(self.theme)
        self.remember_me.set_style(self.theme)
        self.button_login.set_style(self.theme, "primary")
        self.button_config.set_style(self.theme, "secondary")
        self.toggle_password_btn.set_style(self.theme, "secondary")
        self.toggle_password_btn.setProperty("compactButton", True)
        self._apply_title_label_style()
        if hasattr(self, "network_status_label") and self.network_status_label:
            self.network_status_label.setStyleSheet(
                self._build_network_label_style(
                    level=self._network_gate_level,
                    blocked=self._network_gate_blocked,
                )
            )

