from datetime import date, datetime, time, timedelta

from django.db.models import Q, F
from django.views.generic import TemplateView

from sncfgtfs.models import Stop, StopTime, CalendarDate, Calendar


class GareView(TemplateView):
    template_name = "sncfgtfs/gare.html"

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        stop = Stop.objects.filter(name__iexact=kwargs["gare"], location_type=1).first()
        context['stop'] = stop
        next_departures = []

        now = datetime.now()
        if self.request.GET.get('date', None):
            query_date = date.fromisoformat(self.request.GET['date'])
        else:
            query_date = now.date()
        if self.request.GET.get('time', None):
            query_time = time.fromisoformat(self.request.GET['time'])
        else:
            query_time = now.time()
        context['query_date'] = query_date
        context['query_time'] = query_time

        query_time = query_time.isoformat(timespec='seconds')
        query_time = timedelta(seconds=int(query_time[:2]) * 3600 + int(query_time[3:5]) * 60 + int(query_time[6:]))

        yesterday = query_date - timedelta(days=1)
        time_yesterday = query_time + timedelta(days=1)

        tomorrow = query_date + timedelta(days=1)

        qs = StopTime.objects.annotate(departure_time_24h=F('departure_time')).none()
        for child in Stop.objects.filter(name__iexact=kwargs["gare"], location_type=0).all():
            qs_child = StopTime.objects.filter(stop=child, pickup_type=0)
            qs_child_tod = qs_child.filter(Q(departure_time__gte=query_time) &
                                           (Q(trip__service_id__in=CalendarDate.objects.filter(
                                                date=query_date, exception_type=1).values_list('service_id'))
                                            | Q(trip__service_id__in=Calendar.objects.filter(
                                                    start_date__lte=query_date,
                                                    end_date__gte=query_date,
                                                    **{f"{query_date:%A}".lower(): True})
                                                .filter(~Q(id__in=CalendarDate.objects.filter(
                                                             date=query_date, exception_type=2)
                                                           .values_list('service_id')))
                                                .values_list('id')))) \
                .annotate(departure_time_24h=F('departure_time'))

            qs_child_yes = qs_child.filter(Q(departure_time__gte=time_yesterday) &
                                           (Q(trip__service_id__in=CalendarDate.objects.filter(
                                                date=yesterday, exception_type=1).values_list('service_id'))
                                            | Q(trip__service_id__in=Calendar.objects.filter(
                                                    start_date__lte=yesterday,
                                                    end_date__gte=yesterday,
                                                    **{f"{yesterday:%A}".lower(): True})
                                                .filter(~Q(id__in=CalendarDate.objects.filter(
                                                             date=yesterday, exception_type=2)
                                                           .values_list('service_id')))
                                                .values_list('id')))) \
                .annotate(departure_time_24h=F('departure_time') - timedelta(days=1))

            qs_child_tom = qs_child.filter(Q(departure_time__gte=timedelta(0)) &
                                           (Q(trip__service_id__in=CalendarDate.objects.filter(
                                                date=tomorrow, exception_type=1).values_list('service_id'))
                                            | Q(trip__service_id__in=Calendar.objects.filter(
                                                    start_date__lte=tomorrow,
                                                    end_date__gte=tomorrow,
                                                    **{f"{tomorrow:%A}".lower(): True})
                                                .filter(~Q(id__in=CalendarDate.objects.filter(
                                                             date=tomorrow, exception_type=2)
                                                             .values_list('service_id')))
                                                .values_list('id')))) \
                .annotate(departure_time_24h=F('departure_time') + timedelta(days=1))
            qs_child = qs_child_tod.union(qs_child_yes).union(qs_child_tom)
            qs = qs.union(qs_child)
        next_departures += qs.order_by("departure_time_24h")[:20].all()
        context['next_departures'] = next_departures
        return context
