import csv
import io
from datetime import datetime, timedelta
from django.utils import timezone
from django.contrib import messages
from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import HttpResponseRedirect, FileResponse, HttpResponse
from django.shortcuts import render
from django.urls import reverse_lazy
from django.views import View
from django.views.generic import TemplateView, CreateView, DetailView, DeleteView, UpdateView
from django_addanother.views import CreatePopupMixin
from reportlab.lib.pagesizes import A4, A5
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.pdfgen import canvas
from textwrap import wrap


from orders_app.forms import OrderForm, OrderLineFormSet, CustomerForm, ProductForm, StoreForm,\
    OrderLineFormSetEdit
from orders_app.models import Order, Store, OrderProduct, Customer, Product


class ExportView(View):
    def get(self, request):
        response = HttpResponse(content_type='text/csv')
        response['Content-Disposition'] = 'attachment; filename="orders.csv"'

        #order_data = Order.objects.all()
        last_month = datetime.today() - timedelta(days=30)
        order_data = Order.objects.filter(order_date__gte=last_month)

        writer = csv.writer(response)
        writer.writerow(['order_id', 'order_date', 'delivery_date', 'store',
                         'product_type', 'amount', 'product_specifications', 'extra_info',
                         'customer_name', 'customer_telephone', 'customer_email',
                         'customer_social', 'order_info'])

        for order in order_data:
            order_products = OrderProduct.objects.filter(order=order.id)
            for prod in order_products:
                if prod.product.name == "ΤΟΥΡΤΑ ΓΕΝΕΘΛΙΩΝ":
                    prod_specs = "ΓΕΥΣΗ={}-ΤΥΠΟΣ={}:{}-".format(prod.cake_flavor, prod.cake_type, prod.cake_type_num)
                    if prod.cake_color_other:
                        prod_specs = "{}-ΧΡΩΜΑ={}-".format(prod_specs, prod.cake_color_other)
                    else:
                        prod_specs = "{}-ΧΡΩΜΑ={}-".format(prod_specs, prod.cake_color)
                    if prod.fyt_color_other:
                        prod_specs = "{}-ΧΡΩΜΑ_ΦΥΤ={}".format(prod_specs, prod.fyt_color_other)
                    else:
                        prod_specs = "{}-ΧΡΩΜΑ_ΦΥΤ={}".format(prod_specs, prod.fyt_color)
                elif prod.product.name == "ΤΟΥΡΤΑ ΒΟΥΤΗΡΟΚΡΕΜΑ-ΖΑΧΑΡΟΠΑΣΤΑ":
                    prod_specs = "3D={}-ΎΨΟΣ={}".format(prod.cream_cake_3d, prod.cream_cake_height)
                elif prod.product.name == "ΤΟΥΡΤΑ ΓΑΜΟΥ-ΑΡΡΑΒΩΝΑ":
                    prod_specs = "ΤΥΠΟΣ={}-ΒΑΣΗ={}-ΓΛΑΣ./ΣΑΝΤ.={}-".format(prod.engagement_cake_type, prod.engagement_cake_base, prod.engagement_cake_glaze)
                    if prod.engagement_cake_pcs_other:
                        prod_specs = "{}-ΤΜΧ={}-".format(prod_specs, prod.engagement_cake_pcs_other)
                    else:
                        prod_specs = "{}-ΤΜΧ={}-".format(prod_specs, prod.engagement_cake_pcs)
                elif prod.product.name == "ΒΑΠΤΙΣΗ":
                    prod_specs = "ΓΕΥΣΗ={}-ΤΥΠΟΣ={}-".format(prod.cup_flavor, prod.cup_type)
                    if prod.cup_color_other:
                        prod_specs = "{}-ΧΡΩΜΑ={}".format(prod_specs, prod.cup_color_other)
                    else:
                        prod_specs = "{}-ΧΡΩΜΑ={}".format(prod_specs, prod.cup_color)
                elif prod.product.name == "CANDY BAR":
                    prod_specs = "ΤΥΠΟΣ={}-ΤΥΛΙΓΜΑ={}-".format(prod.candy_bar_type, prod.candy_bar_wrap)
                    if prod.candy_bar_decor_other:
                        prod_specs = "{}-ΝΤΕΚΟΡ={}".format(prod_specs, prod.candy_bar_decor_other)
                    else:
                        prod_specs = "{}-ΝΤΕΚΟΡ={}".format(prod_specs, prod.candy_bar_decor)
                else:
                    prod_specs = "ΔΙΑΦΟΡΑ"
                writer.writerow([order.id, timezone.localtime(order.order_date).strftime("%d/%m/%Y %H:%M"),
                                 order.delivery_date.strftime("%d/%m/%Y"), order.store,
                                 prod.product.name, prod.amount, prod_specs,
                                 prod.info, order.customer.name, order.customer.telephone,
                                 order.customer.email, order.customer.social_media,
                                 order.order_info])

        return response


class PrintView(View):
    @classmethod
    def obj_writer(cls, c_obj, coord, text_in):
        c_obj.drawString(coord[0], coord[1], text_in)
        if coord[1] <= 25:
            c_obj.showPage()
            return 800
        else:
            return coord[1]

    def get(self, request, pk):
        order_num = self.request.path.split('/')[-2]
        order_data = Order.objects.get(id=order_num)
        order_products = OrderProduct.objects.filter(order=order_num)

        buffer = io.BytesIO()
        pdfmetrics.registerFont(TTFont('DejaVuSans', 'DejaVuSans.ttf'))
        p = canvas.Canvas(buffer, pagesize=A4)
        p.setFont("DejaVuSans", 18)
        self.obj_writer(p, [240, 800], "ΠΑΡΑΓΓΕΛΙΑ #{}".format(order_data.id))
        p.setFont("DejaVuSans", 12)
        self.obj_writer(p, [40, 770], "Κατάσταση:")
        self.obj_writer(p, [220, 770], "{}".format(order_data.order_status))
        self.obj_writer(p, [40, 750], "Πελάτης:")
        self.obj_writer(p, [220, 750], "{} - {}".format(order_data.customer_name, order_data.customer_address))
        self.obj_writer(p, [40, 730], "Τηλέφωνο:")
        self.obj_writer(p, [220, 730], "{} - {}".format(order_data.customer_telephone, order_data.customer_email))
        self.obj_writer(p, [40, 710], "Ημ/νια Παραγγελίας:")
        self.obj_writer(p, [220, 710], "{}".format(timezone.localtime(order_data.order_date).strftime("%d/%m/%Y %H:%M")))
        self.obj_writer(p, [40, 690], "Ημ/νια Παράδοσης:")
        self.obj_writer(p, [220, 690], "{} - {}".format(order_data.delivery_date.strftime("%d/%m/%Y"), order_data.delivery))
        self.obj_writer(p, [40, 670], "Κατάστημα:")
        self.obj_writer(p, [220, 670], "{}".format(order_data.store))
        self.obj_writer(p, [40, 650], "Σχόλια Παραγγελίας:")
        if "\n" in order_data.order_info:
            y = 650
            for line in order_data.order_info.split('\n'):
                if len(line) > 45:
                    step = 45
                    for i in range(0, len(line), 45):
                        n_line = line[i:step]
                        step += 45
                        y = self.obj_writer(p, [220, y], "{}".format(n_line))
                        y -= 15
                else:
                    y = self.obj_writer(p, [220, y], "{}".format(line))
                    y -= 15
        else:
            y = 650
            y = self.obj_writer(p, [220, y], "{}".format(order_data.order_info))
            y -= 15
        p.setFont("DejaVuSans", 16)
        y -= 15
        y = self.obj_writer(p, [170, y], "Προϊόντα Παραγγελίας")
        p.setFont("DejaVuSans", 10)
        y -= 20
        for order_product in order_products:
            y = self.obj_writer(p, [40, y], "Προϊόν:")
            y = self.obj_writer(p, [100, y], "{}".format(order_product.product.name))
            y = self.obj_writer(p, [315, y], "Ποσότητα:")
            y = self.obj_writer(p, [390, y], "{}".format(order_product.amount))
            if order_product.product.name == 'ΤΟΥΡΤΑ ΓΕΝΕΘΛΙΩΝ':
                y -= 15
                y = self.obj_writer(p, [40, y], "Γεύση:")
                y = self.obj_writer(p, [130, y], "{}".format(order_product.cake_flavor))
                y -= 15
                y = self.obj_writer(p, [40, y], "Τύπος:")
                y = self.obj_writer(p, [130, y], "{}".format(order_product.cake_type))
                y = self.obj_writer(p, [315, y], "Νούμερο:")
                y = self.obj_writer(p, [390, y], "{}".format(order_product.cake_type_num))
                if order_product.cake_color == 'ΆΛΛΟ':
                    y -= 15
                    y = self.obj_writer(p, [40, y], "Χρώμα:")
                    y = self.obj_writer(p, [130, y], "{}".format(order_product.cake_color_other))
                else:
                    y -= 15
                    y = self.obj_writer(p, [40, y], "Χρώμα:")
                    y = self.obj_writer(p, [130, y], "{}".format(order_product.cake_color))
                if order_product.fyt_color == 'ΆΛΛΟ':
                    y -= 15
                    y = self.obj_writer(p, [40, y], "Χρώμα Φυτιλ.:")
                    y = self.obj_writer(p, [130, y], "{}".format(order_product.fyt_color_other))
                else:
                    y = self.obj_writer(p, [315, y], "Χρώμα Φυτιλ.:")
                    y = self.obj_writer(p, [390, y], "{}".format(order_product.fyt_color))
            elif order_product.product.name == 'ΤΟΥΡΤΑ ΒΟΥΤΗΡΟΚΡΕΜΑ-ΖΑΧΑΡΟΠΑΣΤΑ':
                y -= 15
                y = self.obj_writer(p, [40, y], "3D:")
                y = self.obj_writer(p, [130, y], "{}".format(order_product.cream_cake_3d))
                y = self.obj_writer(p, [315, y], "Ύψος:")
                y = self.obj_writer(p, [390, y], "{}".format(order_product.cream_cake_height))
            elif order_product.product.name == 'ΤΟΥΡΤΑ ΓΑΜΟΥ-ΑΡΡΑΒΩΝΑ':
                y -= 15
                y = self.obj_writer(p, [40, y], "Τύπος:")
                y = self.obj_writer(p, [130, y], "{}".format(order_product.engagement_cake_type))
                y = self.obj_writer(p, [315, y], "Βάση:")
                y = self.obj_writer(p, [390, y], "{}".format(order_product.engagement_cake_base))
                y -= 15
                if order_product.engagement_cake_pcs == 'ΆΛΛΟ':
                    y = self.obj_writer(p, [40, y], "Τεμάχια:")
                    y = self.obj_writer(p, [130, y], "{}".format(order_product.engagement_cake_pcs_other))
                else:
                    y = self.obj_writer(p, [40, y], "Τεμάχια:")
                    y = self.obj_writer(p, [130, y], "{}".format(order_product.engagement_cake_pcs))
                y = self.obj_writer(p, [315, y], "Γλάσ./Σαντ.:")
                y = self.obj_writer(p, [390, y], "{}".format(order_product.engagement_cake_glaze))
            elif order_product.product.name == 'ΒΑΠΤΙΣΗ':
                y -= 15
                y = self.obj_writer(p, [40, y], "Γεύση:")
                y = self.obj_writer(p, [130, y], "{}".format(order_product.cup_flavor))
                if order_product.cup_color == 'ΆΛΛΟ':
                    y = self.obj_writer(p, [315, y], "Χρώμα:")
                    y = self.obj_writer(p, [390, y], "{}".format(order_product.cup_color_other))
                else:
                    y = self.obj_writer(p, [315, y], "Χρώμα:")
                    y = self.obj_writer(p, [390, y], "{}".format(order_product.cup_color))
                y -= 15
                y = self.obj_writer(p, [40, y], "Τύπος CandyBar:")
                y = self.obj_writer(p, [130, y], "{}".format(order_product.candy_bar_type))
                y -= 15
                if order_product.cup_color == 'ΆΛΛΟ':
                    y = self.obj_writer(p, [315, y], "Ντεκόρ:")
                    y = self.obj_writer(p, [390, y], "{}".format(order_product.candy_bar_decor_other))
                else:
                    y = self.obj_writer(p, [315, y], "Ντεκόρ:")
                    y = self.obj_writer(p, [390, y], "{}".format(order_product.candy_bar_decor))

                y = self.obj_writer(p, [40, y], "Τύλιγμα:")
                y = self.obj_writer(p, [130, y], "{}".format(order_product.candy_bar_wrap))
            elif order_product.product.name == 'CANDY BAR':
                y -= 15
                if order_product.cup_color == 'ΆΛΛΟ':
                    y = self.obj_writer(p, [40, y], "Χρώμα:")
                    y = self.obj_writer(p, [130, y], "{}".format(order_product.cup_color_other))
                else:
                    y = self.obj_writer(p, [40, y], "Χρώμα:")
                    y = self.obj_writer(p, [130, y], "{}".format(order_product.cup_color))
                y -= 15
                y = self.obj_writer(p, [40, y], "Τύπος CandyBar:")
                y = self.obj_writer(p, [130, y], "{}".format(order_product.candy_bar_type))
                y -= 15
                if order_product.cup_color == 'ΆΛΛΟ':
                    y = self.obj_writer(p, [315, y], "Ντεκόρ:")
                    y = self.obj_writer(p, [390, y], "{}".format(order_product.candy_bar_decor_other))
                else:
                    y = self.obj_writer(p, [315, y], "Ντεκόρ:")
                    y = self.obj_writer(p, [390, y], "{}".format(order_product.candy_bar_decor))

                y = self.obj_writer(p, [40, y], "Τύλιγμα:")
                y = self.obj_writer(p, [130, y], "{}".format(order_product.candy_bar_wrap))

            #y -= 15
            #y = self.obj_writer(p, [40, y], "Χρώμα 1:")
            #y = self.obj_writer(p, [100, y], "{}".format(order_product.color1))
            #y = self.obj_writer(p, [315, y], "Χρώμα 2:")
            #y = self.obj_writer(p, [390, y], "{}".format(order_product.color2))
            y -= 15
            y = self.obj_writer(p, [40, y], "Πληροφορίες:")
            if order_product.info:
                if "\n" in order_product.info:
                    for line in order_product.info.split('\n'):
                        if len(line) > 70:
                            step = 70
                            for i in range(0, len(line), 70):
                                n_line = line[i:step]
                                step += 70
                                y = self.obj_writer(p, [130, y], "{}".format(n_line))
                                y -= 15
                        else:
                            y = self.obj_writer(p, [130, y], "{}".format(line))
                            y -= 15
                else:
                    y = self.obj_writer(p, [130, y], "{}".format(order_product.info))
            y -= 20
            p.line(40, y, 560, y)
            y -= 15
        p.showPage()
        p.save()
        buffer.seek(0)
        return FileResponse(buffer, as_attachment=True, filename='Order_{}.pdf'.format(order_data.id))


class DashboardPageView(LoginRequiredMixin, TemplateView):
    template_name = "diaxeirisi/Dashboard.Default.html"

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        if self.request.user.id == 3:
            context["DB_Objects"] = Order.objects.filter(store=1)
        elif self.request.user.id == 4:
            context["DB_Objects"] = Order.objects.filter(store=2)
        elif self.request.user.id == 5:
            context["DB_Objects"] = Order.objects.filter(store=3)
        else:
            context["DB_Objects"] = Order.objects.all()
        context["active_page"] = 'dashboard'
        return context


class ProductPageView(LoginRequiredMixin, TemplateView):
    template_name = "diaxeirisi/Dashboard.Products.html"

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context["DB_Objects"] = Product.objects.all()
        context["active_page"] = 'products'
        return context


class OrderProductsPageView(LoginRequiredMixin, TemplateView):
    template_name = "diaxeirisi/Dashboard.OrderProducts.html"
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        print(self.request.user.id)
        if self.request.user.id == 3:
            order_ids = Order.objects.filter(store=1)
            order_ids = list(answer.id for answer in order_ids)
            context["DB_Objects"] = OrderProduct.objects.filter(order_id__in=order_ids)
        elif self.request.user.id == 4:
            order_ids = Order.objects.filter(store=2)
            order_ids = list(answer.id for answer in order_ids)
            context["DB_Objects"] = OrderProduct.objects.filter(order_id__in=order_ids)
        elif self.request.user.id == 5:
            order_ids = Order.objects.filter(store=3)
            order_ids = list(answer.id for answer in order_ids)
            context["DB_Objects"] = OrderProduct.objects.filter(order_id__in=order_ids)
        else:
            context["DB_Objects"] = OrderProduct.objects.all()
        context["active_page"] = 'products'
        return context


class StorePageView(LoginRequiredMixin, TemplateView):
    template_name = "diaxeirisi/Dashboard.Stores.html"

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context["DB_Objects"] = Store.objects.all()
        context["active_page"] = 'store'
        return context


class CustomerPageView(LoginRequiredMixin, TemplateView):
    template_name = "diaxeirisi/Dashboard.Customers.html"

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context["DB_Objects"] = Customer.objects.all()
        context["active_page"] = 'customers'
        return context



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

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


class CustomerDelete(DeleteView):
    model = Customer
    template_name = 'orders/customer_delete.html'
    success_url ="/dx/customers/"


class CustomerCreate(CreatePopupMixin, CreateView):
    model = Customer
    template_name = 'orders/customer_create.html'
    form_class = CustomerForm
    success_url = reverse_lazy('orders_app:customer_create')

    def form_valid(self, form):
        success_url = reverse_lazy('orders_app:customer_create')
        messages.success(self.request, "Ο πελάτης δημιουργήθηκε")
        super().form_valid(form)
        return HttpResponseRedirect(success_url)


class ProductDelete(DeleteView):
    model = Product
    template_name = 'orders/product_delete.html'
    success_url ="/dx/products"


class ProductCreate(CreatePopupMixin, CreateView):
    model = Product
    template_name = 'orders/product_create.html'
    form_class = ProductForm
    success_url = reverse_lazy('orders_app:product_create')

    def form_valid(self, form):
        success_url = reverse_lazy('orders_app:product_create')
        messages.success(self.request, "To προϊόν δημιουργήθηκε")
        super().form_valid(form)
        return HttpResponseRedirect(success_url)


class StoreDelete(DeleteView):
    model = Store
    template_name = 'orders/store_delete.html'
    success_url ="/dx/stores/"


class StoreCreate(LoginRequiredMixin, CreatePopupMixin, CreateView):
    model = Store
    template_name = 'orders/store_create.html'
    form_class = StoreForm
    success_url = reverse_lazy('orders_app:store_create')

    def form_valid(self, form):
        success_url = reverse_lazy('orders_app:store_create')
        messages.success(self.request, "To Κατάστημα δημιουργήθηκε")
        super().form_valid(form)
        return HttpResponseRedirect(success_url)


class OrderDelete(DeleteView):
    model = Order
    template_name = 'orders/order_delete.html'
    success_url ="/dx"


class OrderCreate(CreateView):
    model = Order
    template_name = 'orders/order_create.html'
    form_class = OrderForm

    def get_context_data(self, **kwargs):
        data = super(OrderCreate, self).get_context_data(**kwargs)
        if not self.request.POST:
            data['order_products'] = OrderLineFormSet()
        return data

    def post(self, request, *args, **kwargs):
        form = self.get_form()
        order_products = OrderLineFormSet(self.request.POST, self.request.FILES, instance=form.instance)
        if form.is_valid() and order_products.is_valid():
            order = form.save()
            order_lines = order_products.save(commit=False)
            for line in order_lines:
                line.save()
            messages.success(self.request, "Η παραγγελία αποθηκευτηκέ <a class='float-right badge badge-pill badge-light' href='/dx/order/print/{}'>Εκτύπωση</a>".format(order.id))

            return HttpResponseRedirect(request.META['HTTP_REFERER'])
        else:
            form_errors = order_products.errors
            #print(form_errors)
            return render(request, 'orders/order_create.html', context={'form': form, 'order_products': order_products, 'form_errors': form_errors})

    def get_success_url(self):
        return reverse_lazy('orders_app:order_detail', kwargs={'pk': self.object.pk})


class OrderUpdate(UpdateView):
    model = Order
    form_class = OrderForm
    template_name = 'orders/order_create.html'

    def get_success_url(self):
        return reverse_lazy('orders_app:order_update', kwargs={'pk': self.object.pk})

    def get_form_class(self):
        return OrderForm

    def get_order_id(self):
        return self.kwargs['pk']

    def get_context_data(self, **kwargs):
        context = super(OrderUpdate, self).get_context_data(**kwargs)
        if self.request.POST:
            context['order_products'] = OrderLineFormSetEdit(self.request.POST, self.request.FILES, instance=self.object)
        else:
            context['order_products'] = OrderLineFormSetEdit(instance=self.object)
        return context

    def post(self, request, *args, **kwargs):
        order_data = Order.objects.get(id=self.get_order_id())
        #order_line_data = OrderProduct.objects.filter(order=self.get_order_id())
        form = OrderForm(self.request.POST, self.request.FILES, instance=order_data) #, initial={model_to_dict(order_data)}
        order_products = OrderLineFormSetEdit(self.request.POST, self.request.FILES, instance=form.instance)
        if form.is_valid() and order_products.is_valid():
            form.save()
            for inline_form in order_products:
                if not inline_form.cleaned_data['DELETE']:
                    inline_form.save()

            messages.success(self.request, "Η παραγγελία αποθηκευτηκέ")
            return HttpResponseRedirect(request.META['HTTP_REFERER'])
        else:
            form_errors = order_products.errors
            #print(form_errors)
            return render(request, 'orders/order_create.html',
                          context={'form': form, 'order_products': order_products, 'form_errors': form_errors})

