import argparse
import pytest
import umnet_napalm
import napalm
from pathlib import Path
import json
from pprint import pprint


def mock_netmiko_send(path: str, cmd: str) -> str:
    """
    Generic 'translate a device command to a valid filename, then read
    data from that file'
    path: Path object pointing to where that file resides
    cmd: the command string passed to the relevant netmiko/junper/etc "send_command" method
    """
    cmd = cmd.replace(" ", "_")
    cmd = cmd.replace("*", "star") + ".txt"

    cmd_file = str(path + "/" + cmd)

    with open(cmd_file, encoding="utf-8") as fh:
        return fh.read()


def mock_junos_view(path: str, cmd: str) -> str:
    """
    Calls 'get' for junos view against a file instead of a live deivce
    """
    view = getattr(umnet_napalm.junos.junos_views, cmd)
    fixture_file = f"{path}/{view.GET_RPC}.xml"
    result = view(path=fixture_file)  # pylint: disable=no-member
    return result.get()


## each umnet_napalm class needs to be patched differently
## because of how they're implemented.
PATCHES = {
    # classes that inherit netmiko-based NAPALM drivers
    "ios": (napalm.ios.ios.IOSDriver, "_send_command", mock_netmiko_send),
    "nxos_ssh": (napalm.nxos_ssh.NXOSSSHDriver, "_send_command", mock_netmiko_send),
    # classes that implement their own netmiko-based driver
    "iosxr": (umnet_napalm.iosxr.IOSXR, "_send_command", mock_netmiko_send),
    "asa": (umnet_napalm.asa.ASA, "_send", mock_netmiko_send),
    # junos view
    "junos": (umnet_napalm.Junos, "_send_command", mock_junos_view),
}


def mock_get(monkeypatch, test_folder: str):
    """
    Based on path in "mock_data" folder, runs the appropriate getter
    code against the appropriate platform and returns the results
    """

    folder = Path(test_folder)
    if not folder.exists():
        raise FileNotFoundError(f"No test folder {test_folder}")

    test_name = folder.parts[-1]
    getter = folder.parts[-2]
    platform = folder.parts[-3]

    (patch_class, patch_method, mock_method) = PATCHES[platform]

    def patch_send(self, cmd):
        return mock_method(test_folder, cmd)

    driver = umnet_napalm.get_network_driver(platform)(
        test_name, "fake_user", "fake_password"
    )
    monkeypatch.setattr(patch_class, patch_method, patch_send)
    result = getattr(driver, getter)()

    return result


if __name__ == "__main__":
    MOCK_DATA_DIR = Path(__file__).parent / "mock_data"

    parser = argparse.ArgumentParser(
        description="""Generate mock output data based on raw router input saved in the mock_data directory"""
    )
    parser.add_argument("platform", choices=umnet_napalm.PLATFORM_MAP)
    parser.add_argument("getter", type=str)
    parser.add_argument("test_name", type=str)

    args = parser.parse_args()

    test_dir = MOCK_DATA_DIR / args.platform / args.getter / args.test_name

    result = mock_get(pytest.MonkeyPatch(), str(test_dir))
    print(
        f"**** Generating {test_dir}/expected_result.json with the following data ****"
    )
    pprint(result)

    with open(f"{test_dir}/expected_result.json", "w", encoding="utf-8") as fh:
        json.dump(result, fh, indent=4)
