# edited by glg
from pypos.core.utils.config_utils import read_app_settings, save_app_settings


SCANNER_SETTINGS_DEFAULTS = {
    "scanner_detector_enabled": 0,
    "scanner_max_inter_char_ms": 50,
    "scanner_min_length": 5,
    "scanner_require_enter_suffix": 1,
    "scanner_duplicate_guard_ms": 180,
    "scanner_backend_mode": "wedge",
    "scanner_rawinput_enabled": 1,
    "scanner_rawinput_whitelist": [],
}


def _as_int(value, default, min_value=None):
    try:
        parsed = int(float(value))
    except (TypeError, ValueError):
        parsed = int(default)
    if min_value is not None and parsed < int(min_value):
        return int(default)
    return int(parsed)


def _as_bool(value, default=False):
    if value is None:
        return bool(default)
    if isinstance(value, bool):
        return value
    text = str(value).strip().lower()
    if text in {"1", "true", "yes", "on"}:
        return True
    if text in {"0", "false", "no", "off"}:
        return False
    try:
        return int(float(value)) > 0
    except (TypeError, ValueError):
        return bool(default)


def _normalize_backend_mode(value):
    mode = str(value or "wedge").strip().lower()
    if mode not in {"auto", "wedge", "rawinput"}:
        return "wedge"
    return mode


def _normalize_whitelist(raw):
    if not isinstance(raw, list):
        return []
    values = []
    seen = set()
    for item in raw:
        if isinstance(item, dict):
            token = str(item.get("match") or item.get("value") or "").strip().lower()
        else:
            token = str(item or "").strip().lower()
        if not token or token in seen:
            continue
        values.append(token)
        seen.add(token)
    return values


def read_scanner_settings():
    cfg = dict(SCANNER_SETTINGS_DEFAULTS)
    cfg.update(read_app_settings() or {})
    return {
        "enabled": _as_bool(cfg.get("scanner_detector_enabled"), False),
        "max_inter_char_ms": _as_int(cfg.get("scanner_max_inter_char_ms"), 50, min_value=1),
        "min_length": _as_int(cfg.get("scanner_min_length"), 5, min_value=1),
        "require_enter_suffix": _as_bool(cfg.get("scanner_require_enter_suffix"), True),
        "duplicate_guard_ms": _as_int(cfg.get("scanner_duplicate_guard_ms"), 180, min_value=1),
        "backend_mode": _normalize_backend_mode(cfg.get("scanner_backend_mode")),
        "rawinput_enabled": _as_bool(cfg.get("scanner_rawinput_enabled"), True),
        "rawinput_whitelist": _normalize_whitelist(cfg.get("scanner_rawinput_whitelist", [])),
    }


def save_scanner_settings(payload):
    data = payload if isinstance(payload, dict) else {}
    current = read_scanner_settings()
    enabled = _as_bool(data.get("enabled"), current.get("enabled", False))
    max_inter_char_ms = _as_int(
        data.get("max_inter_char_ms", current.get("max_inter_char_ms", 50)),
        current.get("max_inter_char_ms", 50),
        min_value=1,
    )
    min_length = _as_int(
        data.get("min_length", current.get("min_length", 5)),
        current.get("min_length", 5),
        min_value=1,
    )
    require_enter_suffix = _as_bool(
        data.get("require_enter_suffix"),
        current.get("require_enter_suffix", True),
    )
    duplicate_guard_ms = _as_int(
        data.get("duplicate_guard_ms", current.get("duplicate_guard_ms", 180)),
        current.get("duplicate_guard_ms", 180),
        min_value=1,
    )
    backend_mode = _normalize_backend_mode(data.get("backend_mode", current.get("backend_mode")))
    rawinput_enabled = _as_bool(data.get("rawinput_enabled"), current.get("rawinput_enabled", True))
    rawinput_whitelist = _normalize_whitelist(data.get("rawinput_whitelist", current.get("rawinput_whitelist", [])))
    save_app_settings(
        {
            "scanner_detector_enabled": 1 if enabled else 0,
            "scanner_max_inter_char_ms": max_inter_char_ms,
            "scanner_min_length": min_length,
            "scanner_require_enter_suffix": 1 if require_enter_suffix else 0,
            "scanner_duplicate_guard_ms": duplicate_guard_ms,
            "scanner_backend_mode": backend_mode,
            "scanner_rawinput_enabled": 1 if rawinput_enabled else 0,
            "scanner_rawinput_whitelist": rawinput_whitelist,
        }
    )
    return read_scanner_settings()
