from __future__ import absolute_import, print_function

import six

from collections import defaultdict
from datetime import datetime, timedelta
from django.utils import timezone
from time import time

from sentry.models import (
    Activity, Group, GroupStatus, Project, ProjectOption
)
from sentry.tasks.base import instrumented_task

ONE_HOUR = 3600


@instrumented_task(name='sentry.tasks.schedule_auto_resolution',
                   time_limit=75,
                   soft_time_limit=60)
def schedule_auto_resolution():
    options = ProjectOption.objects.filter(
        key__in=['sentry:resolve_age', 'sentry:_last_auto_resolve'],
    )
    opts_by_project = defaultdict(dict)
    for opt in options:
        opts_by_project[opt.project_id][opt.key] = opt.value

    cutoff = time() - ONE_HOUR
    for project_id, options in six.iteritems(opts_by_project):
        if not options.get('sentry:resolve_age'):
            # kill the option to avoid it coming up in the future
            ProjectOption.objects.filter(
                key__in=['sentry:_last_auto_resolve', 'sentry:resolve_age'],
                project=project_id,
            ).delete()
            continue

        if int(options.get('sentry:_last_auto_resolve', 0)) > cutoff:
            continue

        auto_resolve_project_issues.delay(
            project_id=project_id,
            expires=ONE_HOUR,
        )


@instrumented_task(name='sentry.tasks.auto_resolve_project_issues',
                   time_limit=75,
                   soft_time_limit=60)
def auto_resolve_project_issues(project_id, cutoff=None, chunk_size=1000,
                                **kwargs):
    project = Project.objects.get_from_cache(id=project_id)

    age = project.get_option('sentry:resolve_age', None)
    if not age:
        return

    project.update_option('sentry:_last_auto_resolve', int(time()))

    if cutoff:
        cutoff = datetime.utcfromtimestamp(cutoff).replace(tzinfo=timezone.utc)
    else:
        cutoff = timezone.now() - timedelta(hours=int(age))

    queryset = list(Group.objects.filter(
        project=project,
        last_seen__lte=cutoff,
        status=GroupStatus.UNRESOLVED,
    )[:chunk_size])

    might_have_more = len(queryset) == chunk_size

    for group in queryset:
        happened = Group.objects.filter(
            id=group.id,
            status=GroupStatus.UNRESOLVED,
        ).update(
            status=GroupStatus.RESOLVED,
            resolved_at=timezone.now(),
        )

        if happened:
            Activity.objects.create(
                group=group,
                project=project,
                type=Activity.SET_RESOLVED_BY_AGE,
                data={
                    'age': age,
                },
            )

    if might_have_more:
        auto_resolve_project_issues.delay(
            project_id=project_id,
            cutoff=int(cutoff.strftime('%s')),
            chunk_size=chunk_size,
        )
