# edited by glg
import itertools
import sqlite3
import tempfile

import pytest

import pypos.modules.auth.services.device_registration_service as drs_module
from pypos.modules.auth.services.device_registration_service import DeviceRegistrationService

pytestmark = [pytest.mark.unit]


def _stub_common(monkeypatch, service):
    monkeypatch.setattr(service, "set_web_admin_url", lambda _url: "https://demo.mayagrahakencana.com/jodomart_pypos")
    monkeypatch.setattr(drs_module, "save_config", lambda _cfg: None)
    monkeypatch.setattr(service, "get_machine_id", lambda: "MID-TEST-001")


def test_search_store_branches_requires_web_admin():
    service = DeviceRegistrationService()
    result = service.search_store_branches(web_admin_url="", toko_id="1001")
    assert result["ok"] is False
    assert "Web Admin wajib diisi" in result["message"]


def test_search_store_branches_existing_device_shortcut(monkeypatch):
    service = DeviceRegistrationService()
    _stub_common(monkeypatch, service)
    monkeypatch.setattr(
        service,
        "_probe_existing_device_on_server",
        lambda machine_id, toko_id_int: {
            "status": 200,
            "ok": True,
            "data_reg": {"cabang_nama": "cabang utama"},
            "result": {"status": 200},
        },
    )
    result = service.search_store_branches(
        web_admin_url="https://demo.mayagrahakencana.com/jodomart_pypos",
        toko_id="1001",
    )
    assert result["ok"] is True
    assert result.get("already_registered") is True
    assert result.get("auto_close") is True


def test_search_store_branches_pending_device_shortcut(monkeypatch):
    service = DeviceRegistrationService()
    _stub_common(monkeypatch, service)
    monkeypatch.setattr(
        service,
        "_probe_existing_device_on_server",
        lambda machine_id, toko_id_int: {
            "status": 202,
            "ok": True,
            "data_reg": {"cabang_nama": "cabang utama"},
            "result": {"status": 202},
        },
    )
    result = service.search_store_branches(
        web_admin_url="https://demo.mayagrahakencana.com/jodomart_pypos",
        toko_id="1001",
    )
    assert result["ok"] is True
    assert result.get("pending_approval") is True
    assert result.get("auto_close") is True


def test_search_store_branches_dynamic_filtering(monkeypatch):
    service = DeviceRegistrationService()
    _stub_common(monkeypatch, service)
    monkeypatch.setattr(
        service,
        "_probe_existing_device_on_server",
        lambda machine_id, toko_id_int: {"status": 404, "ok": False, "result": {"status": 404}},
    )
    monkeypatch.setattr(
        drs_module,
        "get_branch_rows",
        lambda toko_id=None: [
            {"id": -1, "nama": "pusat", "toko_id": 1001, "status": 1, "trash": 0},
            {"id": 100, "nama": "cabang utama", "toko_id": 1001, "status": 1, "trash": 0},
            {"id": 101, "nama": "cabang ke dua", "toko_id": 1001, "status": 0, "trash": 0},
            {"id": 102, "nama": "trash", "toko_id": 1001, "status": 1, "trash": 1},
            {"id": 200, "nama": "toko lain", "toko_id": 2002, "status": 1, "trash": 0},
        ],
    )
    monkeypatch.setattr(service, "_replace_branches_for_toko", lambda toko_id, rows: None)

    result = service.search_store_branches(
        web_admin_url="https://demo.mayagrahakencana.com/jodomart_pypos",
        toko_id="1001",
    )
    assert result["ok"] is True
    branch_pairs = result.get("branches") or []
    assert len(branch_pairs) == 2
    assert ("pusat", "-1") in branch_pairs
    assert ("cabang utama", "100") in branch_pairs


def test_search_store_branches_not_found(monkeypatch):
    service = DeviceRegistrationService()
    _stub_common(monkeypatch, service)
    monkeypatch.setattr(
        service,
        "_probe_existing_device_on_server",
        lambda machine_id, toko_id_int: {"status": 404, "ok": False, "result": {"status": 404}},
    )
    monkeypatch.setattr(drs_module, "get_branch_rows", lambda toko_id=None: [])
    monkeypatch.setattr(service, "_replace_branches_for_toko", lambda toko_id, rows: None)

    result = service.search_store_branches(
        web_admin_url="https://demo.mayagrahakencana.com/jodomart_pypos",
        toko_id="1001",
    )
    assert result["ok"] is False
    assert "tidak ditemukan" in result["message"].lower()
    assert result["error_code"] == "AUTH_BRANCHES_NOT_FOUND"
    assert result["reason"] == "branches_not_found"
    assert str(result.get("trace_id") or "").startswith("auth-search_store_branches-")


def test_register_device_rejects_incomplete_required_fields(monkeypatch):
    service = DeviceRegistrationService()
    _stub_common(monkeypatch, service)
    monkeypatch.setattr(
        service,
        "_probe_existing_device_on_server",
        lambda machine_id, toko_id_int: {"status": 404, "ok": False, "result": {"status": 404}},
    )
    result = service.register_device(
        alias="",
        keterangan="",
        cabang_nama="",
        cabang_id="",
        nama_pengguna="kasir",
        web_admin_url="https://demo.mayagrahakencana.com/jodomart_pypos",
        toko_id="1001",
    )
    assert result["ok"] is False
    assert "lengkapi field" in result["message"].lower()


def test_register_device_existing_approved_shortcut(monkeypatch):
    service = DeviceRegistrationService()
    _stub_common(monkeypatch, service)
    monkeypatch.setattr(
        service,
        "_probe_existing_device_on_server",
        lambda machine_id, toko_id_int: {
            "status": 200,
            "ok": True,
            "data_reg": {"cabang_nama": "cabang utama"},
            "result": {"status": 200},
        },
    )
    result = service.register_device(
        alias="kasir-1",
        keterangan="meja depan",
        cabang_nama="cabang utama",
        cabang_id="100",
        nama_pengguna="kasir",
        web_admin_url="https://demo.mayagrahakencana.com/jodomart_pypos",
        toko_id="1001",
    )
    assert result["ok"] is True
    assert result.get("already_registered") is True


def test_register_device_existing_pending_shortcut(monkeypatch):
    service = DeviceRegistrationService()
    _stub_common(monkeypatch, service)
    monkeypatch.setattr(
        service,
        "_probe_existing_device_on_server",
        lambda machine_id, toko_id_int: {
            "status": 202,
            "ok": True,
            "data_reg": {"cabang_nama": "cabang utama"},
            "result": {"status": 202},
        },
    )
    result = service.register_device(
        alias="kasir-1",
        keterangan="meja depan",
        cabang_nama="cabang utama",
        cabang_id="100",
        nama_pengguna="kasir",
        web_admin_url="https://demo.mayagrahakencana.com/jodomart_pypos",
        toko_id="1001",
    )
    assert result["ok"] is True
    assert result.get("pending_approval") is True


def test_register_device_existing_server_local_persist_failed(monkeypatch):
    service = DeviceRegistrationService()
    _stub_common(monkeypatch, service)
    monkeypatch.setattr(
        service,
        "_probe_existing_device_on_server",
        lambda machine_id, toko_id_int: {
            "status": 200,
            "ok": False,
            "result": {"status": 200},
            "data_reg": {"cabang_nama": "cabang utama"},
        },
    )

    result = service.register_device(
        alias="kasir-1",
        keterangan="meja depan",
        cabang_nama="cabang utama",
        cabang_id="100",
        nama_pengguna="kasir",
        web_admin_url="https://demo.mayagrahakencana.com/jodomart_pypos",
        toko_id="1001",
    )
    assert result["ok"] is False
    assert result["error_code"] == "AUTH_DEVICE_LOCAL_PERSIST_FAILED"
    assert result["reason"] == "device_local_persist_failed"
    assert str(result.get("trace_id") or "").startswith("auth-register_device-")


def test_register_device_success_sets_first_login_flags(monkeypatch):
    service = DeviceRegistrationService()
    _stub_common(monkeypatch, service)
    monkeypatch.setattr(
        service,
        "_probe_existing_device_on_server",
        lambda machine_id, toko_id_int: {"status": 404, "ok": False, "result": {"status": 404}},
    )
    monkeypatch.setattr(drs_module, "post_device_registration", lambda payload: {"status": 200, "message": "ok"})
    monkeypatch.setattr(drs_module, "simpan_device_pending_lokal", lambda data, device_id=None: True)

    called_keys = []

    def _set_bool(key, value):
        called_keys.append((key, bool(value)))

    monkeypatch.setattr(drs_module, "set_bool", _set_bool)
    result = service.register_device(
        alias="kasir-1",
        keterangan="meja depan",
        cabang_nama="cabang utama",
        cabang_id="100",
        nama_pengguna="kasir",
        web_admin_url="https://demo.mayagrahakencana.com/jodomart_pypos",
        toko_id="1001",
    )
    assert result["ok"] is True
    assert "registrasi berhasil" in result["message"].lower()
    assert ("first_install_done", True) in called_keys
    assert ("first_sync_pending", True) in called_keys
    assert ("per_employee_seed_pending", True) in called_keys
    assert ("per_employee_seed_done", False) in called_keys


def test_register_device_conflict_cabang_fallback_to_existing(monkeypatch):
    service = DeviceRegistrationService()
    _stub_common(monkeypatch, service)
    probe_results = itertools.chain(
        [{"status": 404, "ok": False, "result": {"status": 404}}],
        [
            {
                "status": 200,
                "ok": True,
                "data_reg": {"cabang_nama": "cabang utama"},
                "result": {"status": 200},
            }
        ],
    )
    monkeypatch.setattr(service, "_probe_existing_device_on_server", lambda machine_id, toko_id_int: next(probe_results))
    monkeypatch.setattr(
        drs_module,
        "post_device_registration",
        lambda payload: {"status": 0, "reason": "conflict_cabang_id", "message": "conflict_cabang_id"},
    )
    monkeypatch.setattr(drs_module, "set_bool", lambda key, value: None)

    result = service.register_device(
        alias="kasir-1",
        keterangan="meja depan",
        cabang_nama="cabang utama",
        cabang_id="100",
        nama_pengguna="kasir",
        web_admin_url="https://demo.mayagrahakencana.com/jodomart_pypos",
        toko_id="1001",
    )
    assert result["ok"] is True
    assert result.get("already_registered") is True


def test_replace_branches_keeps_gudang_fields_when_schema_available(monkeypatch):
    service = DeviceRegistrationService()
    with tempfile.TemporaryDirectory() as td:
        db_path = f"{td}/device_reg.db"
        conn = sqlite3.connect(db_path)
        cur = conn.cursor()
        cur.execute(
            """
            CREATE TABLE per_cabang (
                id INTEGER,
                last_update TEXT,
                nama TEXT,
                kelurahan TEXT,
                kecamatan TEXT,
                kabupaten TEXT,
                propinsi TEXT,
                alamat TEXT,
                toko_id TEXT,
                status INTEGER,
                trash INTEGER,
                jenis TEXT,
                harga_jenis TEXT,
                point_jenis TEXT,
                dtime TEXT,
                creator_nama TEXT,
                opname_jenis TEXT,
                gudang_id INTEGER,
                gudang_nama TEXT
            )
            """
        )
        conn.commit()
        conn.close()

        monkeypatch.setattr(drs_module, "connect_sqlite", lambda: sqlite3.connect(db_path))
        service._replace_branches_for_toko(
            toko_id="1001",
            branch_rows=[
                {
                    "id": 101,
                    "nama": "Cabang A",
                    "toko_id": "1001",
                    "status": 1,
                    "trash": 0,
                    "gudang_id": -1010,
                    "gudang_nama": "Gudang A",
                }
            ],
        )
        conn2 = sqlite3.connect(db_path)
        cur2 = conn2.cursor()
        cur2.execute("SELECT gudang_id, gudang_nama FROM per_cabang WHERE id = 101 LIMIT 1")
        row = cur2.fetchone()
        conn2.close()

    assert row is not None
    assert int(row[0] or 0) == -1010
    assert str(row[1] or "") == "Gudang A"
