# edited by glg
import pytest

import pypos.modules.scanner.controllers.scanner_controller as scanner_controller_module
from pypos.modules.scanner.controllers.scanner_controller import ScannerController

pytestmark = [pytest.mark.unit]


class _SettingsServiceStub:
    def __init__(self):
        self.store = {"enabled": False, "rawinput_whitelist": []}

    def load(self):
        return dict(self.store)

    def save(self, payload):
        self.store = dict(payload or {})
        return dict(self.store)


class _PairingServiceStub:
    def normalize_discovered_devices(self, raw_devices):
        rows = raw_devices if isinstance(raw_devices, list) else []
        return list(rows)

    def pair_device(self, current_settings, selected_device, replace=False):
        _ = replace
        current = dict(current_settings or {})
        selected = selected_device if isinstance(selected_device, dict) else {}
        token = str(selected.get("token") or "").strip().lower()
        if not token:
            return None
        current["rawinput_whitelist"] = [token]
        return current


class _DiagnosticServiceStub:
    def run(self, settings, runtime=None):
        _ = runtime
        return {"overall_status": "PASS", "settings": dict(settings or {})}


class _RuntimeServiceStub:
    def __init__(self, settings, log_warning=None, log_debug=None):
        _ = log_warning
        _ = log_debug
        self.settings = dict(settings or {})
        self.started = False
        self.discovered = [{"name": "Scanner USB", "token": "hid#vid_05e0&pid_1200"}]

    def start(self):
        self.started = True

    def stop(self):
        self.started = False

    def apply_settings(self, settings):
        self.settings = dict(settings or {})

    def consume_qt_key_event(self, event):
        _ = event
        return "barcode-qt"

    def poll_pending_barcode(self):
        return "barcode-poll"

    def accept_manual_barcode(self, barcode):
        return str(barcode or "").strip()

    def get_runtime_status(self):
        return {"settings": dict(self.settings), "rawinput": {"active": self.started}}

    def get_discovered_devices(self):
        return list(self.discovered)


def _build_controller(monkeypatch):
    monkeypatch.setattr(scanner_controller_module, "ScannerSettingsService", _SettingsServiceStub)
    monkeypatch.setattr(scanner_controller_module, "ScannerPairingService", _PairingServiceStub)
    monkeypatch.setattr(scanner_controller_module, "ScannerDiagnosticService", _DiagnosticServiceStub)
    monkeypatch.setattr(scanner_controller_module, "ScannerRuntimeService", _RuntimeServiceStub)
    return ScannerController()


def test_scanner_controller_start_and_dispose(monkeypatch):
    ctrl = _build_controller(monkeypatch)
    assert ctrl.runtime_service.started is True
    ctrl.dispose()
    assert ctrl.runtime_service.started is False


def test_scanner_controller_save_settings_apply_runtime(monkeypatch):
    ctrl = _build_controller(monkeypatch)
    saved = ctrl.save_settings({"enabled": True, "rawinput_whitelist": ["hid#vid_05e0&pid_1200"]})
    assert saved["enabled"] is True
    assert ctrl.runtime_service.settings["enabled"] is True


def test_scanner_controller_pair_device_persist_whitelist(monkeypatch):
    ctrl = _build_controller(monkeypatch)
    out = ctrl.pair_device({"name": "Scanner USB", "token": "hid#vid_05e0&pid_1200"}, replace=True)
    assert out is not None
    assert out["rawinput_whitelist"] == ["hid#vid_05e0&pid_1200"]
