from datetime import timedelta

from django.test import TestCase
from django.utils import timezone

from freezegun import freeze_time

from newsreader.news.collection.feed import FeedDuplicateHandler
from newsreader.news.collection.tests.factories import FeedFactory
from newsreader.news.core.models import Post
from newsreader.news.core.tests.factories import FeedPostFactory


@freeze_time("2019-10-30 12:30:00")
class FeedDuplicateHandlerTestCase(TestCase):
    def setUp(self):
        self.maxDiff = None

    def test_duplicate_entries_with_remote_identifiers(self):
        rule = FeedFactory()

        FeedPostFactory.create(
            remote_identifier="28f79ae4-8f9a-11e9-b143-00163ef6bee7", rule=rule
        )

        new_posts = FeedPostFactory.build_batch(
            remote_identifier="28f79ae4-8f9a-11e9-b143-00163ef6bee7",
            publication_date=timezone.now() - timedelta(days=7),
            rule=rule,
            size=5,
        )
        last_post = FeedPostFactory.build(
            remote_identifier="28f79ae4-8f9a-11e9-b143-00163ef6bee7",
            publication_date=timezone.now(),
            rule=rule,
        )

        with FeedDuplicateHandler(rule) as duplicate_handler:
            posts = duplicate_handler.check((*new_posts, last_post))

        self.assertEquals(len(posts), 1)

        post = posts[0]

        self.assertEquals(
            post.publication_date.strftime("%Y-%m-%d %H-%M-%S"),
            last_post.publication_date.strftime("%Y-%m-%d %H-%M-%S"),
        )
        self.assertEquals(post.title, last_post.title)
        self.assertEquals(post.body, last_post.body)
        self.assertEquals(post.rule, last_post.rule)
        self.assertEquals(post.read, False)

    def test_duplicate_entries_with_different_remote_identifiers(self):
        rule = FeedFactory()

        FeedPostFactory(
            remote_identifier="28f79ae4-8f9a-11e9-b143-00163ef6bee7",
            url="https://bbc.com",
            title="New post",
            body="Body",
            publication_date=timezone.now() - timedelta(minutes=10),
            rule=rule,
        )

        new_posts = FeedPostFactory.build_batch(
            remote_identifier="28f79ae4-8f9a-11e9-b143-00163ef6bee7Q",
            url="https://bbc.com",
            title="New post",
            body="Body",
            publication_date=timezone.now() - timedelta(minutes=5),
            rule=rule,
            size=5,
        )
        last_post = FeedPostFactory.build(
            remote_identifier="28f79ae4-8f9a-11e9-b143-00163ef6bee7Q",
            url="https://bbc.com",
            title="New post",
            body="Body",
            publication_date=timezone.now(),
            rule=rule,
        )

        with FeedDuplicateHandler(rule) as duplicate_handler:
            posts = duplicate_handler.check((*new_posts, last_post))

        self.assertEquals(len(posts), 1)

        post = posts[0]

        self.assertEquals(
            post.publication_date.strftime("%Y-%m-%d %H-%M-%S"),
            last_post.publication_date.strftime("%Y-%m-%d %H-%M-%S"),
        )
        self.assertEquals(post.title, last_post.title)
        self.assertEquals(post.body, last_post.body)
        self.assertEquals(post.rule, last_post.rule)
        self.assertEquals(post.read, False)

    def test_duplicate_entries_in_recent_database(self):
        rule = FeedFactory()

        FeedPostFactory(
            url="https://www.bbc.co.uk/news/uk-england-birmingham-48339080",
            title="Birmingham head teacher threatened over LGBT lessons",
            body="Google's move to end business ties with Huawei will affect current devices",
            publication_date=timezone.now() - timedelta(minutes=10),
            remote_identifier=None,
            rule=rule,
        )

        new_posts = FeedPostFactory.build_batch(
            url="https://www.bbc.co.uk/news/uk-england-birmingham-48339080",
            title="Birmingham head teacher threatened over LGBT lessons",
            body="Google's move to end business ties with Huawei will affect current devices",
            publication_date=timezone.now() - timedelta(minutes=5),
            remote_identifier=None,
            rule=rule,
            size=5,
        )

        last_post = FeedPostFactory.build(
            url="https://www.bbc.co.uk/news/uk-england-birmingham-48339080",
            title="Birmingham head teacher threatened over LGBT lessons",
            body="Google's move to end business ties with Huawei will affect current devices",
            publication_date=timezone.now(),
            remote_identifier=None,
            rule=rule,
        )

        with FeedDuplicateHandler(rule) as duplicate_handler:
            posts = duplicate_handler.check((*new_posts, last_post))

        self.assertEquals(len(posts), 1)

        post = posts[0]

        self.assertEquals(
            post.publication_date.strftime("%Y-%m-%d %H-%M-%S"),
            last_post.publication_date.strftime("%Y-%m-%d %H-%M-%S"),
        )
        self.assertEquals(post.title, last_post.title)
        self.assertEquals(post.body, last_post.body)
        self.assertEquals(post.rule, last_post.rule)
        self.assertEquals(post.read, False)

    def test_multiple_existing_entries_with_identifier(self):
        rule = FeedFactory()

        FeedPostFactory.create_batch(
            remote_identifier="28f79ae4-8f9a-11e9-b143-00163ef6bee7", rule=rule, size=5
        )

        new_posts = FeedPostFactory.build_batch(
            remote_identifier="28f79ae4-8f9a-11e9-b143-00163ef6bee7",
            publication_date=timezone.now() - timedelta(hours=5),
            rule=rule,
            size=5,
        )
        last_post = FeedPostFactory.build(
            remote_identifier="28f79ae4-8f9a-11e9-b143-00163ef6bee7",
            publication_date=timezone.now() - timedelta(minutes=5),
            rule=rule,
        )

        with FeedDuplicateHandler(rule) as duplicate_handler:
            posts = duplicate_handler.check((*new_posts, last_post))

        self.assertEquals(len(posts), 1)

        self.assertEquals(
            Post.objects.filter(
                remote_identifier="28f79ae4-8f9a-11e9-b143-00163ef6bee7"
            ).count(),
            1,
        )

        post = posts[0]

        self.assertEquals(
            post.publication_date.strftime("%Y-%m-%d %H-%M-%S"),
            last_post.publication_date.strftime("%Y-%m-%d %H-%M-%S"),
        )
        self.assertEquals(post.title, last_post.title)
        self.assertEquals(post.body, last_post.body)
        self.assertEquals(post.rule, last_post.rule)
        self.assertEquals(post.read, False)

    def test_duplicate_entries_outside_time_slot(self):
        rule = FeedFactory()

        FeedPostFactory(
            url="https://www.bbc.co.uk/news/uk-england-birmingham-48339080",
            title="Birmingham head teacher threatened over LGBT lessons",
            body="Google's move to end business ties with Huawei will affect current devices",
            publication_date=timezone.now(),
            remote_identifier=None,
            rule=rule,
        )

        new_posts = FeedPostFactory.build_batch(
            url="https://www.bbc.co.uk/news/uk-england-birmingham-48339080",
            title="Birmingham head teacher threatened over LGBT lessons",
            body="Google's move to end business ties with Huawei will affect current devices",
            publication_date=timezone.now() + timedelta(minutes=12),
            remote_identifier=None,
            rule=rule,
            size=5,
        )
        last_post = FeedPostFactory.build(
            url="https://www.bbc.co.uk/news/uk-england-birmingham-48339080",
            title="Birmingham head teacher threatened over LGBT lessons",
            body="Google's move to end business ties with Huawei will affect current devices",
            publication_date=timezone.now() + timedelta(minutes=13),
            remote_identifier=None,
            rule=rule,
        )

        with FeedDuplicateHandler(rule) as duplicate_handler:
            posts = duplicate_handler.check((*new_posts, last_post))

        self.assertEquals(len(posts), 1)

        post = posts[0]

        self.assertEquals(post.pk, None)
        self.assertEquals(
            post.publication_date.strftime("%Y-%m-%d %H-%M-%S"),
            last_post.publication_date.strftime("%Y-%m-%d %H-%M-%S"),
        )
        self.assertEquals(post.title, last_post.title)
        self.assertEquals(post.body, last_post.body)
        self.assertEquals(post.rule, last_post.rule)
        self.assertEquals(post.read, False)

    def test_duplicate_entries_in_collected_entries(self):
        rule = FeedFactory()
        post_1 = FeedPostFactory.build(
            title="title got updated",
            body="body",
            url="https://bbc.com",
            publication_date=timezone.now(),
            rule=rule,
        )
        duplicate_post_1 = FeedPostFactory.build(
            title="title got updated",
            body="body",
            url="https://bbc.com",
            publication_date=timezone.now() - timedelta(minutes=5),
            rule=rule,
        )

        post_2 = FeedPostFactory.build(
            remote_identifier="28f79ae4-8f9a-11e9-b143-00163ef6bee7",
            publication_date=timezone.now(),
        )
        duplicate_post_2 = FeedPostFactory.build(
            remote_identifier="28f79ae4-8f9a-11e9-b143-00163ef6bee7",
            publication_date=timezone.now() - timedelta(minutes=5),
        )

        collected_posts = (post_1, post_2, duplicate_post_1, duplicate_post_2)

        with FeedDuplicateHandler(rule) as duplicate_handler:
            posts = duplicate_handler.check(collected_posts)

        self.assertEquals(len(posts), 2)

        post = posts[0]

        self.assertEquals(
            post_1.publication_date.strftime("%Y-%m-%d %H-%M-%S"),
            post.publication_date.strftime("%Y-%m-%d %H-%M-%S"),
        )
        self.assertEquals(post_1.title, post.title)
        self.assertEquals(post_1.body, post.body)
        self.assertEquals(post_1.rule, post.rule)
        self.assertEquals(post.read, False)

        post = posts[1]

        self.assertEquals(
            post_2.publication_date.strftime("%Y-%m-%d %H-%M-%S"),
            post.publication_date.strftime("%Y-%m-%d %H-%M-%S"),
        )
        self.assertEquals(post_2.title, post.title)
        self.assertEquals(post_2.body, post.body)
        self.assertEquals(post_2.rule, post.rule)
        self.assertEquals(post.read, False)
