from django.db.models import F
from django.utils import timezone

from misago.threads.permissions import exclude_invisible_threads

from misago.readtracker import signals
from misago.readtracker.dates import is_date_tracked
from misago.readtracker.models import ForumRead


__all__ = ['make_read_aware', 'sync_record']


def make_read_aware(user, forums):
    if not hasattr(forums, '__iter__'):
        forums = [forums]

    if user.is_anonymous():
        make_read(forums)
        return None

    forums_dict = {}
    for forum in forums:
        forum.last_read_on = user.reads_cutoff
        forum.is_read = not is_date_tracked(forum.last_post_on, user)
        if not forum.is_read:
            forums_dict[forum.pk] = forum

    if forums_dict:
        for record in user.forumread_set.filter(forum__in=forums_dict.keys()):
            forum = forums_dict[record.forum_id]
            forum.last_read_on = record.last_read_on
            forum.is_read = forum.last_read_on >= forum.last_post_on


def make_read(forums):
    now = timezone.now()
    for forum in forums:
        forum.last_read_on = now
        forum.is_read = True


def start_record(user, forum):
    user.forumread_set.create(forum=forum, last_read_on=user.reads_cutoff)


def sync_record(user, forum):
    cutoff_date = user.reads_cutoff

    try:
        forum_record = user.forumread_set.get(forum=forum)
        if forum_record.last_read_on > cutoff_date:
            cutoff_date = forum_record.last_read_on
    except ForumRead.DoesNotExist:
        forum_record = None

    recorded_threads = forum.thread_set.filter(last_post_on__gt=cutoff_date)
    recorded_threads = exclude_invisible_threads(recorded_threads, user, forum)

    all_threads_count = recorded_threads.count()

    read_threads = user.threadread_set.filter(
        forum=forum, last_read_on__gt=cutoff_date)
    read_threads_count = read_threads.filter(
        thread__last_post_on__lte=F("last_read_on")).count()

    forum_is_read = read_threads_count == all_threads_count

    if forum_is_read:
        signals.forum_read.send(sender=user, forum=forum)

    if forum_record:
        if forum_is_read:
            forum_record.last_read_on = forum_record.last_read_on
        else:
            forum_record.last_read_on = cutoff_date
        forum_record.save(update_fields=['last_read_on'])
    else:
        if forum_is_read:
            last_read_on = timezone.now()
        else:
            last_read_on = cutoff_date

        forum_record = user.forumread_set.create(
            forum=forum,
            last_read_on=last_read_on)


def read_forum(user, forum):
    try:
        forum_record = user.forumread_set.get(forum=forum)
        forum_record.last_read_on = timezone.now()
        forum_record.save(update_fields=['last_read_on'])
    except ForumRead.DoesNotExist:
        user.forumread_set.create(forum=forum, last_read_on=timezone.now())
    signals.forum_read.send(sender=user, forum=forum)