import copy
from pathlib import Path
from typing import Optional, Union

import safe_radix32
from clarabot_nano_common.common.config.constants import NanoServeAPI
from clarabot_nano_common.common.crypto.keyring import NanoSelfAccountKeyring, NanoPeerAccountKeyring

from clarabot_nano_tests.testing.file import read_yaml


def get_initial_context_truth_for_dbg_handler(
    req: bytes,
    owner_kr: NanoSelfAccountKeyring,
    peer_id: int,
    peer_kr: Optional[NanoPeerAccountKeyring] = None,
    room_data: Optional[dict] = None,
    remote_yaml: Optional[Union[str, Path]] = None,
    **room_kwargs
) -> dict:
    """
    For gateway context creation testing this can produce the context from test data to a limited extent.
    For room permissions the room-config would be needed but that is not  managed in sync from the reset-state as
    it diverges by mutations. Thus a server query would be necessary.
    The remote_ip is left out as it may change by the test's infrastructure.
    """
    assert NanoServeAPI.DRIVE_V1 == 1
    assert NanoServeAPI.DRIVE_V2 == 2
    assert NanoServeAPI.DRIVE_V3 == 3
    assert NanoServeAPI.DRIVE_V4 == 4
    assert NanoServeAPI.DRIVE_V5 == 5
    assert NanoServeAPI.DRIVE_V6 == 6
    assert NanoServeAPI.DRIVE_V7 == 7
    assert NanoServeAPI.DRIVE_V8 == 8 == NanoServeAPI.DRIVE_CURRENT
    assert NanoServeAPI.DRIVE_EXT_DOCUMENT_V1 == 16 == NanoServeAPI.DRIVE_EXT_DOCUMENT_CURRENT
    assert peer_kr is None  # TODO
    config = None
    if remote_yaml:
        assert remote_yaml, str(remote_yaml)
        config = read_yaml(remote_yaml)
    if room_data:
        assert config
        apis = {}
        for drive in config["drives"]:
            serves = dict(drive)
            serves.pop("rooms", None)
            for room_id in drive.get("rooms", []):
                if safe_radix32.decode(room_id) == room_data["id"]:
                    # TODO: depends on drive extensions as well
                    assert NanoServeAPI.DRIVE_V1 not in apis  # TODO
                    assert NanoServeAPI.DRIVE_V2 not in apis  # TODO
                    assert NanoServeAPI.DRIVE_V3 not in apis  # TODO
                    assert NanoServeAPI.DRIVE_V4 not in apis  # TODO
                    assert NanoServeAPI.DRIVE_V5 not in apis  # TODO
                    assert NanoServeAPI.DRIVE_V6 not in apis  # TODO
                    assert NanoServeAPI.DRIVE_V7 not in apis  # TODO
                    assert NanoServeAPI.DRIVE_V8 not in apis  # TODO
                    apis[NanoServeAPI.DRIVE_CURRENT] = copy.deepcopy(serves)
        room = {
            "id": room_data["id"],
            "kr": {
                "id": safe_radix32.encode_fw(room_data["id"]),
                "keys": {"1": room_data["_room_kr"].get_key("1")},
            },
            "room_apis": apis,
            **room_kwargs,
        }
    else:
        room = None
    return {
        "owner_kr": {
            "id": owner_kr.id.decode(),
            "public_keys": {"1": owner_kr.get_public_key("1"), "2": owner_kr.get_public_key("2")},
            "secret_keys": {
                "1": owner_kr.get_secret_key("1"),
                "2": owner_kr.get_secret_key("2"),
                "3": owner_kr.get_secret_key("3"),
            },
        },
        "peer_kr": None,
        "admin_csp": None,
        "admin_st": None,
        # "remote_ip": None,
        "part_size": 500000,
        "part_approx": [375000, 125000],
        "s_hmac_parts": [48, 96],
        "owner_account_id": safe_radix32.decode(owner_kr.id.decode()),
        "account_id": peer_id,
        "cache_key": None,
        "transfer_key": None,
        "part": None,
        "room": room,
        "request_head": req[:128],
    }
