"""
Tests for pages services.
"""
from datetime import timedelta

from django.utils import timezone

import pytest
from django_mock_queries.query import MockSet

import pages.services
from feed.models import News
from users.models import User
from pages.services import get_latest_news


@pytest.mark.django_db()
def test_get_latest_news():
    user = User.objects.create(username="test", email="test@example.com")
    first_news = News.objects.create(comment="First news", user=user)
    second_news = News.objects.create(comment="Second news", user=user)
    old_news = News.objects.create(comment="Old news", user=user)
    old_news.created_at = timezone.now() - timedelta(8)
    old_news.save()
    News.objects.create(
        comment="Comment",
        user=user,
        parent=first_news,
    )

    news = get_latest_news()

    assert list(news) == [second_news, first_news]


@pytest.mark.django_db()
def test_get_latest_news_limit():
    user = User.objects.create(username="test", email="test@example.com")
    for i in range(20):
        News.objects.create(comment=f"News {i}", user=user)

    news = get_latest_news()

    assert len(news) == 15


@pytest.mark.django_db()
def test_get_latest_news_annotate_likes_count(mocker):
    user = User.objects.create(username="test", email="test@example.com")
    News.objects.create(comment="News", user=user)
    count_spy = mocker.spy(pages.services, "Count")

    news_list = get_latest_news()
    news = news_list.values()[0]

    assert "likes_count" in news
    count_spy.assert_called_once_with("news_likes")


@pytest.mark.django_db()
def test_get_latest_news_prefetch_data(mocker):
    user = User.objects.create(username="test", email="test@example.com")
    news_object = News.objects.create(
        comment="This is a publication",
        user=user,
    )
    related_mock = mocker.patch(
        "django.db.models.query.prefetch_related_objects",
        MockSet(),
    )
    prefetch_mock = mocker.patch("pages.services.Prefetch")

    list(get_latest_news())

    related_mock.assert_called_once_with(
        [news_object],
        prefetch_mock(),
        "comments",
    )


@pytest.mark.django_db()
def test_get_latest_news_prefetch_user_with_card(mocker):
    user = User.objects.create(username="test", email="test@example.com")
    News.objects.create(
        comment="This is a publication",
        user=user,
    )
    mocker.patch(
        "django.db.models.query.prefetch_related_objects",
        MockSet(),
    )
    prefetch_mock = mocker.patch("pages.services.Prefetch")
    cards_mock = mocker.patch("pages.services.Card.objects.filter")

    list(get_latest_news())

    cards_mock.assert_called_once_with(default=True)
    prefetch_mock.assert_called_once_with("user__cards", queryset=cards_mock())


@pytest.mark.django_db()
def test_get_latest_news_custom_date_range():
    user = User.objects.create(username="test", email="test@example.com")
    news_object = News.objects.create(comment="News", user=user)
    old_news = News.objects.create(comment="Old news", user=user)
    old_news.created_at = timezone.now() - timedelta(3)
    old_news.save()

    news = get_latest_news(2)

    assert list(news) == [news_object]
