import logging
from datetime import datetime
from django.conf import settings
from django.utils import timezone
from django.shortcuts import render, reverse, redirect, get_object_or_404
from django.http import HttpResponseRedirect
from django.urls import reverse, reverse_lazy
from django.views.generic.base import RedirectView, TemplateView
from django.views.generic.edit import FormView, CreateView, UpdateView, DeleteView, FormMixin
from django.views.generic.detail import DetailView, SingleObjectMixin
from django.views.generic.list import ListView
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin
from django.forms import inlineformset_factory

from django.db.models import (
    Exists, OuterRef, Prefetch, Subquery, Count, Sum, Avg, F, Q, Value
)
from django.db.models.functions import Coalesce

from accounts.models import User
from accounts.utils import get_or_create_customer
from accounts.forms import AddressForm
from core.models import Product, Order, OrderLine

from core import DiscountValueType, VoucherType, OrderStatus, ShippingMethodType
from .forms import OrderLineFulfillForm, OrderLineFormset

logger = logging.getLogger(__name__)

class DashboardHomeView(TemplateView):
    template_name = 'dashboard/dashboard_detail.html'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        today = timezone.localtime(timezone.now()).date()
        context['order_count'] = Order.objects.filter(
            created_at__date=today
        ).count()
        context['orders_unfulfilled'] = Order.objects.filter(
            status=OrderStatus.UNFULFILLED
        ).count()
        context['todays_sales'] = Order.objects.filter(
            created_at__date=today
        ).aggregate(total=Sum('total_net_amount'))['total']
        return context

class OrderListView(ListView):
    model = Order
    template_name = 'dashboard/order_list.html'

    def get_queryset(self):
        query = self.request.GET.get('status')
        order = self.request.GET.get('order')
        if query:
            object_list = Order.objects.filter(
                status=query
            ).order_by(
                '-created_at'
            ).select_related(
                'customer'
            )

        else:
            object_list = Order.objects.order_by(
                '-created_at'
            ).select_related(
                'customer'
            )

        return object_list

class OrderDetailView(DetailView):
    model = Order
    template_name = 'dashboard/order_detail.html'

    def get_object(self):
        queryset = Order.objects.filter(
            pk=self.kwargs.get(self.pk_url_kwarg)
        ).select_related(
            'customer',
            'billing_address',
            'shipping_address',
            'shipping_method'
        ).prefetch_related(
            'lines__product__productphoto_set'
        )
        obj = queryset.get()
        return obj

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        return context


class OrderFulfillView(UpdateView):
    model = Order
    template_name = "dashboard/order_fulfill.html"
    form_class = OrderLineFormset

    def form_valid(self, form):
        form.save()
        return HttpResponseRedirect(self.get_success_url())

    def get_success_url(self):
        return reverse('dashboard:order-detail', kwargs={'pk': self.object.pk})


def order_fulfill(request, pk):
    order = Order.objects.get(pk=pk)
    OrderLineFormset = inlineformset_factory(Order, OrderLine, form=OrderLineFulfillForm, extra=0, can_delete=False)
    if request.method == "POST":
        formset = OrderLineFormset(request.POST, request.FILES, instance=order)
        if formset.is_valid():
            formset.save()
            # Do something. Should generally end with a redirect. For example:
            return HttpResponseRedirect(order.get_absolute_url())

    else:
        formset = OrderLineFormset(instance=order)
    return render(request, 'dashboard/order_fulfill.html', {'formset': formset, 'order': order})


class ProductListView(ListView):
    model = Product
    template_name = 'dashboard/product_list.html'

    # def get_queryset(self):
    #     object_list = Product.objects.filter(
    #         status=OrderStatus.UNFULFILLED
    #     ).select_related(
    #         'customer'
    #     )
    #     return object_list

class ProductDetailView(DetailView):
    model = Product
    template_name = 'dashboard/product_detail.html'

class ProductCreateView(CreateView):
    model = Product
    template_name = "dashboard/product_create_form.html"
    fields = '__all__'


class CustomerListView(ListView):
    model = User
    template_name = 'dashboard/customer_list.html'

    def get_queryset(self):
        object_list = User.objects.filter(
            Exists(
                Order.objects.filter(customer=OuterRef('pk'))
            ) | Q(is_staff=False)
        ).prefetch_related(
            'orders'
        ).annotate(
            num_orders=Count('orders')
        )

        return object_list

class CustomerDetailView(DetailView):
    model = User
    template_name = 'dashboard/customer_detail.html'
    context_object_name = 'customer'

class CustomerUpdateView(UpdateView):
    model = User
    template_name = 'dashboard/customer_form.html'
    context_object_name = 'customer'
    fields = (
        'first_name',
        'last_name',
        'email',
        'is_staff',
        'addresses',
        'default_shipping_address'
    )

    def get_success_url(self):
        return reverse('dashboard:customer-detail', kwargs={'pk': self.object.pk})

