# edited by glg
import sqlite3
from typing import Any, Callable, Dict

from pypos.core.utils.config_utils import get_current_server_hash
from pypos.core.utils.device_utils import get_active_device_info, get_device_id


class TransactionExportDeviceContextService:
    def __init__(
        self,
        *,
        connect_fn: Callable[[], Any],
        as_positive_int_fn: Callable[[Any, int], int],
        logger=None,
    ):
        self._connect_fn = connect_fn
        self._as_positive_int_fn = as_positive_int_fn
        self._logger = logger

    def _log_warning(self, message, *args):
        logger = self._logger
        if logger is None:
            return
        try:
            logger.warning(message, *args)
        except Exception:
            return

    def _log_debug(self, message, *args):
        logger = self._logger
        if logger is None:
            return
        try:
            logger.debug(message, *args)
        except Exception:
            return

    def _as_positive_int(self, value, default=0):
        try:
            return int(self._as_positive_int_fn(value, default))
        except Exception:
            return int(default or 0)

    def get_export_device_context(
        self,
        *,
        machine_id_hint: str = "",
        cache: Dict[str, Dict[str, Any]] = None,
    ) -> Dict[str, Any]:
        machine_hint = str(machine_id_hint or get_device_id() or "").strip()
        cache_store = cache if isinstance(cache, dict) else {}
        cache_key = machine_hint or "__current__"
        cached = cache_store.get(cache_key)
        if isinstance(cached, dict):
            return dict(cached)

        context: Dict[str, Any] = {
            "id": 0,
            "machine_id": machine_hint,
            "cabang_id": 0,
            "cabang_nama": "",
            "toko_id": 0,
            "cpu_info": "",
            "com_info": "",
        }
        server_hash = get_current_server_hash()

        try:
            conn = self._connect_fn()
            try:
                cur = conn.cursor()
                if machine_hint:
                    cur.execute(
                        """
                        SELECT id, machine_id, cabang_id, cabang_nama, toko_id, cpu_info, com_info
                        FROM per_cabang_device
                        WHERE machine_id = ?
                          AND status = 1
                          AND trash = 0
                          AND server_hash = ?
                        ORDER BY id DESC
                        LIMIT 1
                        """,
                        (machine_hint, server_hash),
                    )
                    row = cur.fetchone()
                    if not row:
                        cur.execute(
                            """
                            SELECT id, machine_id, cabang_id, cabang_nama, toko_id, cpu_info, com_info
                            FROM per_cabang_device
                            WHERE machine_id = ?
                              AND status = 1
                              AND trash = 0
                              AND (server_hash IS NULL OR server_hash = '')
                            ORDER BY id DESC
                            LIMIT 1
                            """,
                            (machine_hint,),
                        )
                        row = cur.fetchone()
                else:
                    cur.execute(
                        """
                        SELECT id, machine_id, cabang_id, cabang_nama, toko_id, cpu_info, com_info
                        FROM per_cabang_device
                        WHERE status = 1
                          AND trash = 0
                          AND server_hash = ?
                        ORDER BY id DESC
                        LIMIT 1
                        """,
                        (server_hash,),
                    )
                    row = cur.fetchone()
                    if not row:
                        cur.execute(
                            """
                            SELECT id, machine_id, cabang_id, cabang_nama, toko_id, cpu_info, com_info
                            FROM per_cabang_device
                            WHERE status = 1
                              AND trash = 0
                              AND (server_hash IS NULL OR server_hash = '')
                            ORDER BY id DESC
                            LIMIT 1
                            """
                        )
                        row = cur.fetchone()

                if row:
                    context["id"] = self._as_positive_int(row[0], 0)
                    context["machine_id"] = str(row[1] or machine_hint or "").strip()
                    context["cabang_id"] = self._as_positive_int(row[2], 0)
                    context["cabang_nama"] = str(row[3] or "").strip()
                    context["toko_id"] = self._as_positive_int(row[4], 0)
                    context["cpu_info"] = str(row[5] or "").strip()
                    context["com_info"] = str(row[6] or "").strip()
            finally:
                conn.close()
        except (sqlite3.Error, RuntimeError, ValueError, TypeError) as exc:
            self._log_warning("[DEBUG EXPORT] gagal baca context device export: %s", exc)

        # Fallback ke device aktif untuk menjaga payload tetap terisi.
        try:
            active_info = get_active_device_info(machine_hint) or {}
            if isinstance(active_info, dict):
                if not str(context.get("machine_id") or "").strip():
                    context["machine_id"] = str(
                        active_info.get("machine_id") or machine_hint or ""
                    ).strip()
                if self._as_positive_int(context.get("cabang_id"), 0) <= 0:
                    context["cabang_id"] = self._as_positive_int(active_info.get("cabang_id"), 0)
                if self._as_positive_int(context.get("toko_id"), 0) <= 0:
                    context["toko_id"] = self._as_positive_int(active_info.get("toko_id"), 0)
                if not str(context.get("cabang_nama") or "").strip():
                    context["cabang_nama"] = str(active_info.get("cabang_nama") or "").strip()
        except (ValueError, TypeError, RuntimeError, sqlite3.Error) as exc:
            self._log_debug("[DEBUG EXPORT] fallback active device context diabaikan: %s", exc)

        if not str(context.get("machine_id") or "").strip():
            context["machine_id"] = str(get_device_id() or "").strip()
        if not str(context.get("cpu_info") or "").strip():
            context["cpu_info"] = "no-cpuINFO"
        if not str(context.get("com_info") or "").strip():
            context["com_info"] = "no-comINFO"

        cache_store[cache_key] = dict(context)
        return dict(context)
