"""
Integration tests for the saltutil module.
"""


import logging
import time

import pytest
import salt.defaults.events
from tests.support.helpers import slowTest

log = logging.getLogger(__name__)

pytestmark = [pytest.mark.windows_whitelisted]


@pytest.fixture(autouse=True)
def refresh_pillar(salt_call_cli, salt_minion):
    ret = salt_call_cli.run("saltutil.refresh_pillar", wait=True)
    assert ret.exitcode == 0
    assert ret.json
    try:
        yield
    finally:
        ret = salt_call_cli.run("saltutil.refresh_pillar", wait=True)
        assert ret.exitcode == 0
        assert ret.json


@pytest.fixture(scope="module")
def event_listener(salt_factories):
    return salt_factories.event_listener


@slowTest
@pytest.mark.parametrize("sync_refresh", [False, True])
def test_pillar_refresh(
    salt_minion,
    salt_call_cli,
    event_listener,
    base_env_pillar_tree_root_dir,
    sync_refresh,
):
    """
    test pillar refresh module
    """
    pillar_key = "it-worked-{}".format("sync" if sync_refresh else "async")
    top_pillar_contents = """
    base:
      '*':
        - add-pillar-{}
    """.format(
        "sync" if sync_refresh else "async"
    )
    add_pillar_contents = """
    {0}: {0}
    """.format(
        pillar_key
    )

    ret = salt_call_cli.run("pillar.raw")
    assert ret.exitcode == 0
    assert ret.json
    pre_pillar = ret.json
    # Remove keys which are not important and consume too much output when reading through failures
    for key in ("master", "ext_pillar_opts"):
        pre_pillar.pop(key, None)
    assert pillar_key not in pre_pillar

    top_file = pytest.helpers.temp_file(
        "top.sls", top_pillar_contents, base_env_pillar_tree_root_dir
    )
    add_pillar_file = pytest.helpers.temp_file(
        "add-pillar-{}.sls".format("sync" if sync_refresh else "async"),
        add_pillar_contents,
        base_env_pillar_tree_root_dir,
    )

    with top_file, add_pillar_file:
        start_time = time.time()
        stop_time = start_time + 120

        ret = salt_call_cli.run(
            "--retcode-passthrough", "saltutil.refresh_pillar", wait=sync_refresh,
        )
        assert ret.exitcode == 0

        minion_event = None
        expected_tag = salt.defaults.events.MINION_PILLAR_REFRESH_COMPLETE
        event_pattern = (salt_minion.id, expected_tag)
        while True:
            if time.time() > stop_time:
                pytest.fail("Failed to receive the refresh pillar complete event.")

            if not minion_event:
                events = event_listener.get_events(
                    [event_pattern], after_time=start_time
                )
                for event in events:
                    minion_event = event
                    break

            if minion_event:
                # We got all events back
                break

            time.sleep(0.5)

        log.debug("Refresh pillar complete event received: %s", minion_event)

        ret = salt_call_cli.run("pillar.raw")
        assert ret.exitcode == 0
        assert ret.json
        post_pillar = ret.json
        # Remove keys which are not important and consume too much output when reading through failures
        for key in ("master", "ext_pillar_opts"):
            post_pillar.pop(key, None)
        assert pillar_key in post_pillar
        assert post_pillar[pillar_key] == pillar_key
