# retoor <retoor@molodetz.nl>

import requests
from playwright.sync_api import expect
from tests.conftest import BASE_URL
from devplacepy.database import (
    get_notification_default,
    get_notification_prefs,
    get_table,
    notification_enabled,
    reset_notification_prefs,
    set_notification_default,
    set_notification_pref,
)
from devplacepy.utils import create_notification, generate_uid
def _user_notification_prefs(username):
    return get_table("users").find_one(username=username)
def _pref(prefs, key):
    return next(p for p in prefs if p["key"] == key)


def test_defaults_all_enabled(bob):
    _, user = bob
    uid = _user_notification_prefs(user["username"])["uid"]
    reset_notification_prefs(uid)
    prefs = get_notification_prefs(uid)
    assert prefs, "every notification type must be listed"
    for pref in prefs:
        assert pref["in_app"] is True
        assert pref["push"] is True
        assert pref["customized"] is False
    assert notification_enabled(uid, "vote", "in_app") is True
    assert notification_enabled(uid, "vote", "push") is True


def test_set_pref_channels_are_independent(bob):
    _, user = bob
    uid = _user_notification_prefs(user["username"])["uid"]
    reset_notification_prefs(uid)
    try:
        set_notification_pref(uid, "vote", "push", False)
        assert notification_enabled(uid, "vote", "push") is False
        assert notification_enabled(uid, "vote", "in_app") is True
        vote = _pref(get_notification_prefs(uid), "vote")
        assert vote["push"] is False
        assert vote["in_app"] is True
        assert vote["customized"] is True
        # an untouched type is unaffected
        assert notification_enabled(uid, "follow", "push") is True
    finally:
        reset_notification_prefs(uid)


def test_reset_restores_defaults(bob):
    _, user = bob
    uid = _user_notification_prefs(user["username"])["uid"]
    set_notification_pref(uid, "comment", "in_app", False)
    assert notification_enabled(uid, "comment", "in_app") is False
    reset_notification_prefs(uid)
    assert notification_enabled(uid, "comment", "in_app") is True
    assert _pref(get_notification_prefs(uid), "comment")["customized"] is False


def test_global_default_applies_only_to_untouched_users(alice, bob):
    _, admin = alice
    _, member = bob
    admin_uid = _user_notification_prefs(admin["username"])["uid"]
    member_uid = _user_notification_prefs(member["username"])["uid"]
    reset_notification_prefs(admin_uid)
    set_notification_pref(member_uid, "badge", "push", True)
    try:
        set_notification_default("badge", "push", False)
        # untouched admin inherits the new default
        assert notification_enabled(admin_uid, "badge", "push") is False
        # member with an explicit choice keeps it
        assert notification_enabled(member_uid, "badge", "push") is True
    finally:
        set_notification_default("badge", "push", True)
        reset_notification_prefs(member_uid)
    assert get_notification_default("badge", "push") is True


def test_award_type_listed_in_prefs(bob):
    _, user = bob
    uid = _user_notification_prefs(user["username"])["uid"]
    reset_notification_prefs(uid)
    prefs = get_notification_prefs(uid)
    assert any(pref["key"] == "award" for pref in prefs)


def test_create_notification_honors_award_pref(bob):
    _, user = bob
    uid = _user_notification_prefs(user["username"])["uid"]
    notifications = get_table("notifications")
    reset_notification_prefs(uid)
    try:
        set_notification_pref(uid, "award", "in_app", False)
        suppressed = f"award suppressed {generate_uid()}"
        create_notification(uid, "award", suppressed, uid, "/profile/bob_test?tab=awards")
        assert notifications.find_one(user_uid=uid, message=suppressed) is None
        set_notification_pref(uid, "award", "in_app", True)
        delivered = f"award delivered {generate_uid()}"
        create_notification(uid, "award", delivered, uid, "/profile/bob_test?tab=awards")
        assert notifications.find_one(user_uid=uid, message=delivered) is not None
    finally:
        reset_notification_prefs(uid)


def test_create_notification_honors_in_app_pref(bob):
    _, user = bob
    uid = _user_notification_prefs(user["username"])["uid"]
    notifications = get_table("notifications")
    reset_notification_prefs(uid)
    try:
        set_notification_pref(uid, "follow", "in_app", False)
        suppressed = f"suppressed {generate_uid()}"
        create_notification(uid, "follow", suppressed, uid, "/feed")
        assert notifications.find_one(user_uid=uid, message=suppressed) is None

        set_notification_pref(uid, "follow", "in_app", True)
        delivered = f"delivered {generate_uid()}"
        create_notification(uid, "follow", delivered, uid, "/feed")
        assert notifications.find_one(user_uid=uid, message=delivered) is not None
    finally:
        reset_notification_prefs(uid)


def test_quiz_attempt_type_listed_in_prefs(bob):
    _, user = bob
    uid = _user_notification_prefs(user["username"])["uid"]
    reset_notification_prefs(uid)
    prefs = get_notification_prefs(uid)
    assert any(pref["key"] == "quiz_attempt" for pref in prefs)


def test_create_notification_honors_quiz_attempt_pref(bob):
    _, user = bob
    uid = _user_notification_prefs(user["username"])["uid"]
    notifications = get_table("notifications")
    reset_notification_prefs(uid)
    try:
        set_notification_pref(uid, "quiz_attempt", "in_app", False)
        suppressed = f"quiz suppressed {generate_uid()}"
        create_notification(uid, "quiz_attempt", suppressed, uid, "/quizzes")
        assert notifications.find_one(user_uid=uid, message=suppressed) is None
        set_notification_pref(uid, "quiz_attempt", "in_app", True)
        delivered = f"quiz delivered {generate_uid()}"
        create_notification(uid, "quiz_attempt", delivered, uid, "/quizzes")
        assert notifications.find_one(user_uid=uid, message=delivered) is not None
    finally:
        reset_notification_prefs(uid)
