import pytest

from notifications.notificationevent import (
    BuildSuccessEvent,
    NotificationEvent,
    VulnerabilityFoundEvent,
)
from util.morecollections import AttrDict

from test.fixtures import *


@pytest.mark.parametrize("event_kind", NotificationEvent.event_names())
def test_create_notifications(event_kind):
    assert NotificationEvent.get_event(event_kind) is not None


@pytest.mark.parametrize("event_name", NotificationEvent.event_names())
def test_build_notification(event_name, initialized_db):
    # Create the notification event.
    found = NotificationEvent.get_event(event_name)
    sample_data = found.get_sample_data("foo", "bar", {"level": "low"})

    # Make sure all calls succeed.
    notification_data = {
        "performer_data": {},
    }

    found.get_level(sample_data, notification_data)
    found.get_summary(sample_data, notification_data)
    found.get_message(sample_data, notification_data)


def test_build_emptyjson():
    notification_data = AttrDict(
        {
            "event_config_dict": None,
        }
    )

    # No build data at all.
    assert BuildSuccessEvent().should_perform({}, notification_data)


def test_build_nofilter():
    notification_data = AttrDict(
        {
            "event_config_dict": {},
        }
    )

    # No build data at all.
    assert BuildSuccessEvent().should_perform({}, notification_data)

    # With trigger metadata but no ref.
    assert BuildSuccessEvent().should_perform(
        {
            "trigger_metadata": {},
        },
        notification_data,
    )

    # With trigger metadata and a ref.
    assert BuildSuccessEvent().should_perform(
        {
            "trigger_metadata": {
                "ref": "refs/heads/somebranch",
            },
        },
        notification_data,
    )


def test_build_emptyfilter():
    notification_data = AttrDict(
        {
            "event_config_dict": {"ref-regex": ""},
        }
    )

    # No build data at all.
    assert BuildSuccessEvent().should_perform({}, notification_data)

    # With trigger metadata but no ref.
    assert BuildSuccessEvent().should_perform(
        {
            "trigger_metadata": {},
        },
        notification_data,
    )

    # With trigger metadata and a ref.
    assert BuildSuccessEvent().should_perform(
        {
            "trigger_metadata": {
                "ref": "refs/heads/somebranch",
            },
        },
        notification_data,
    )


def test_build_invalidfilter():
    notification_data = AttrDict(
        {
            "event_config_dict": {"ref-regex": "]["},
        }
    )

    # No build data at all.
    assert not BuildSuccessEvent().should_perform({}, notification_data)

    # With trigger metadata but no ref.
    assert not BuildSuccessEvent().should_perform(
        {
            "trigger_metadata": {},
        },
        notification_data,
    )

    # With trigger metadata and a ref.
    assert not BuildSuccessEvent().should_perform(
        {
            "trigger_metadata": {
                "ref": "refs/heads/somebranch",
            },
        },
        notification_data,
    )


def test_build_withfilter():
    notification_data = AttrDict(
        {
            "event_config_dict": {"ref-regex": "refs/heads/master"},
        }
    )

    # No build data at all.
    assert not BuildSuccessEvent().should_perform({}, notification_data)

    # With trigger metadata but no ref.
    assert not BuildSuccessEvent().should_perform(
        {
            "trigger_metadata": {},
        },
        notification_data,
    )

    # With trigger metadata and a not-matching ref.
    assert not BuildSuccessEvent().should_perform(
        {
            "trigger_metadata": {
                "ref": "refs/heads/somebranch",
            },
        },
        notification_data,
    )

    # With trigger metadata and a matching ref.
    assert BuildSuccessEvent().should_perform(
        {
            "trigger_metadata": {
                "ref": "refs/heads/master",
            },
        },
        notification_data,
    )


def test_build_withwildcardfilter():
    notification_data = AttrDict(
        {
            "event_config_dict": {"ref-regex": "refs/heads/.+"},
        }
    )

    # No build data at all.
    assert not BuildSuccessEvent().should_perform({}, notification_data)

    # With trigger metadata but no ref.
    assert not BuildSuccessEvent().should_perform(
        {
            "trigger_metadata": {},
        },
        notification_data,
    )

    # With trigger metadata and a not-matching ref.
    assert not BuildSuccessEvent().should_perform(
        {
            "trigger_metadata": {
                "ref": "refs/tags/sometag",
            },
        },
        notification_data,
    )

    # With trigger metadata and a matching ref.
    assert BuildSuccessEvent().should_perform(
        {
            "trigger_metadata": {
                "ref": "refs/heads/master",
            },
        },
        notification_data,
    )

    # With trigger metadata and another matching ref.
    assert BuildSuccessEvent().should_perform(
        {
            "trigger_metadata": {
                "ref": "refs/heads/somebranch",
            },
        },
        notification_data,
    )


def test_vulnerability_notification_nolevel():
    notification_data = AttrDict(
        {
            "event_config_dict": {},
        }
    )

    # No level specified.
    assert VulnerabilityFoundEvent().should_perform({}, notification_data)


def test_vulnerability_notification_nopvulninfo():
    notification_data = AttrDict(
        {
            "event_config_dict": {"level": 3},
        }
    )

    # No vuln info.
    assert not VulnerabilityFoundEvent().should_perform({}, notification_data)


def test_vulnerability_notification_normal():
    notification_data = AttrDict(
        {
            "event_config_dict": {"level": 3},
        }
    )

    info = {"vulnerability": {"priority": "Critical"}}
    assert VulnerabilityFoundEvent().should_perform(info, notification_data)
