import os
from io import StringIO

import pytest
from clarabot_nano_common.common.config.constants import CommonConfigConstants

from clarabot_nano.core.bootstrap import core_bootstrap_login
from clarabot_nano.utility import parse_environment_flag
from clarabot_nano_tests.testing.core.common import clear_nano_slots
from clarabot_nano_tests.testing.gateway import start_nano_wait_gateway
from clarabot_nano_tests.testing.server.manager import DevServerManager


@pytest.mark.skipif(parse_environment_flag("CBNANO_TEST_WITHOUT_SERVER"), reason="server-dependant tests disabled")
@pytest.mark.asyncio
async def test_core_bootstrap_login_0(
    monkeypatch,
    capsys,
    reset_user_app_dirs,
    dev_nano_root_dir,
    testing_server_manager: DevServerManager,
    testing_server_user0,
):
    monkeypatch.setattr(CommonConfigConstants, "SERVER_DOMAIN", str(testing_server_manager.server_frontend_domain))
    monkeypatch.setattr(CommonConfigConstants, "SERVER_PATH", str(testing_server_manager.server_frontend_path))
    monkeypatch.setattr(
        CommonConfigConstants, "AIOHTTP_CLIENT_SESSION_OPTS", {"cadata": str(testing_server_manager.ca_certificate)}
    )
    monkeypatch.setitem(os.environ, "CBNANO_ROOT", str(dev_nano_root_dir))

    # FIXME: avoid RuntimeWarning: coroutine 'core_bootstrap_login' was never awaited
    # class _CmdArgs:
    #     local_config = None
    #     bootstrap_login = True
    #
    # with pytest.raises(RuntimeError, match=r"asyncio\.run\(\) cannot be called from a running event loop"):
    #     start_core(_CmdArgs)

    await clear_nano_slots(testing_server_manager, [testing_server_user0["account_id"]])
    async with start_nano_wait_gateway(
        testing_server_manager,
        reset_user_app_dirs,
        dev_nano_root_dir,
        "waiting-config",
    ) as (pm, debug_info, gateway_port, gateway_key):
        assert pm.get_session_id_from_continue_token() is None

        capsys.readouterr()  # clear
        try:
            await core_bootstrap_login(None)
        except SystemExit as e:
            assert e.code == 3
        captured = capsys.readouterr()
        assert captured.out.find("The Nano instance must be stopped to perform bootstrap.") >= 0

    with monkeypatch.context() as m:
        user_input = StringIO(f"{testing_server_user0['email']}\n")
        m.setattr("sys.stdin", user_input)

        def _getpass(*args):
            return testing_server_user0["password"]

        m.setattr("getpass.getpass", _getpass)
        await core_bootstrap_login(None)
    captured = capsys.readouterr()
    assert captured.out.find("No previous session found.") >= 0
    assert captured.out.find("Login successful, new session created!") >= 0

    with monkeypatch.context() as m:
        user_input = StringIO("\ndoit\n")
        m.setattr("sys.stdin", user_input)
        await core_bootstrap_login(None)
    captured = capsys.readouterr()
    assert captured.out.find("Current session is still valid!") >= 0
    assert captured.out.find("WARNING: If the session is shared") >= 0
    assert captured.out.find("Confirmation failed!") >= 0

    async with start_nano_wait_gateway(
        testing_server_manager,
        reset_user_app_dirs,
        dev_nano_root_dir,
        "active",
    ) as (pm, debug_info, gateway_port, gateway_key):
        assert pm.get_session_id_from_continue_token() is not None

    capsys.readouterr()  # clear
    with monkeypatch.context() as m:
        user_input = StringIO("\nlogout\n")
        m.setattr("sys.stdin", user_input)
        await core_bootstrap_login(None)
    captured = capsys.readouterr()
    assert captured.out.find("Current session is still valid!") >= 0
    assert captured.out.find("WARNING: If the session is shared") >= 0
    assert captured.out.find("Session deleted!") >= 0

    async with start_nano_wait_gateway(
        testing_server_manager,
        reset_user_app_dirs,
        dev_nano_root_dir,
        "waiting-config",
    ) as (pm, debug_info, gateway_port, gateway_key):
        assert pm.get_session_id_from_continue_token() is None
