# retoor <retoor@molodetz.nl>

from datetime import date

import pytest

from devplacepy.database import (
    AGE_BANDS,
    MATURITY_TARGETS,
    REPORTABLE_TARGETS,
    REPORT_REASONS,
    SOFT_DELETE_TABLES,
    UNREPORTABLE_TABLES,
    age_band_for,
    years_between,
)
from devplacepy.database.moderation import MODERATION_TABLES


GUIDELINE_REASONS = (
    "hate",
    "violence",
    "weapons",
    "sexual",
    "religious",
    "misinformation",
    "exploitative",
)


def test_every_visible_soft_delete_table_is_reportable():
    reportable_tables = set(REPORTABLE_TARGETS.values())
    excluded = set(UNREPORTABLE_TABLES) | set(MODERATION_TABLES)
    unclassified = [
        table
        for table in SOFT_DELETE_TABLES
        if table not in reportable_tables and table not in excluded
    ]
    assert unclassified == []


def test_exclusion_list_only_names_real_soft_delete_tables():
    unknown = [table for table in UNREPORTABLE_TABLES if table not in SOFT_DELETE_TABLES]
    assert unknown == []


def test_registry_tables_are_unique_and_maturity_is_a_subset():
    assert len(set(REPORTABLE_TARGETS.values())) == len(REPORTABLE_TARGETS)
    assert MATURITY_TARGETS <= set(REPORTABLE_TARGETS)


def test_report_reasons_cover_every_guideline_category():
    for reason in GUIDELINE_REASONS:
        assert reason in REPORT_REASONS
    assert REPORT_REASONS["intellectual_property"]
    assert REPORT_REASONS["other"]


def test_every_registry_target_resolves_to_a_url(local_db):
    from devplacepy.database import resolve_object_url

    for target_type in REPORTABLE_TARGETS:
        url = resolve_object_url(target_type, "missing-uid")
        assert url.startswith("/")


def test_resolve_object_url_points_at_the_owning_surface(local_db):
    from devplacepy.database import get_table, resolve_object_url

    get_table("users").insert(
        {"uid": "mod-user-1", "username": "mod_user_1", "deleted_at": None}
    )
    get_table("messages").insert(
        {
            "uid": "mod-msg-1",
            "sender_uid": "mod-user-1",
            "receiver_uid": "mod-user-2",
            "content": "hello",
        }
    )
    try:
        assert resolve_object_url("user", "mod-user-1") == "/profile/mod_user_1"
        assert (
            resolve_object_url("message", "mod-msg-1")
            == "/messages?with_uid=mod-user-1"
        )
        assert resolve_object_url("devii_output", "anything") == "/devii"
    finally:
        get_table("users").delete(uid="mod-user-1")
        get_table("messages").delete(uid="mod-msg-1")


@pytest.mark.parametrize(
    "age,expected",
    [
        (0, "under_min"),
        (12, "under_min"),
        (13, "13_15"),
        (15, "13_15"),
        (16, "16_17"),
        (17, "16_17"),
        (18, "adult"),
        (120, "adult"),
    ],
)
def test_age_band_boundaries(age, expected):
    assert age_band_for(age) == expected


def test_age_band_is_monotonic_across_the_whole_domain():
    order = {band: index for index, band in enumerate(AGE_BANDS)}
    previous = -1
    for age in range(0, 150):
        current = order[age_band_for(age)]
        assert current >= previous
        previous = current


def test_years_between_handles_leap_days_and_exact_boundaries():
    assert years_between(date(2000, 2, 29), date(2018, 2, 28)) == 17
    assert years_between(date(2000, 2, 29), date(2018, 3, 1)) == 18
    assert years_between(date(2008, 1, 1), date(2026, 1, 1)) == 18
    assert years_between(date(2008, 1, 2), date(2026, 1, 1)) == 17


def test_years_between_never_exceeds_the_calendar_difference():
    born = date(2005, 6, 15)
    for offset in range(0, 4000, 7):
        today = date.fromordinal(born.toordinal() + offset)
        years = years_between(born, today)
        assert 0 <= years <= today.year - born.year
