from rest_framework import viewsets, permissions
from rest_framework.response import Response
from django.db import transaction
from django.utils import timezone

from .models import *
from .serializers import *

from uncloud_pay.helpers import ProductViewSet
from uncloud_pay.models import Order
from uncloud_vm.models import VMProduct, VMDiskProduct

def create_managed_vm(cores, ram, disk_size, image, order):
    # Create VM
    disk = VMDiskProduct(
            owner=order.owner,
            order=order,
            size_in_gb=disk_size,
            image=image)
    vm = VMProduct(
            name="Managed Service Host",
            owner=order.owner,
            cores=cores,
            ram_in_gb=ram,
            primary_disk=disk)
    disk.vm = vm

    vm.save()
    disk.save()

    return vm


class MatrixServiceProductViewSet(ProductViewSet):
    permission_classes = [permissions.IsAuthenticated]
    serializer_class = MatrixServiceProductSerializer

    def get_queryset(self):
        return MatrixServiceProduct.objects.filter(owner=self.request.user)

    def get_serializer_class(self):
        if self.action == 'create':
            return OrderMatrixServiceProductSerializer
        else:
            return MatrixServiceProductSerializer

    @transaction.atomic
    def create(self, request):
        # Extract serializer data.
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        order_recurring_period = serializer.validated_data.pop("recurring_period")
        order_billing_address = serializer.validated_data.pop("billing_address")

        # Create base order.)
        order = Order.objects.create(
                recurring_period=order_recurring_period,
                owner=request.user,
                billing_address=order_billing_address,
                starting_date=timezone.now()
                )
        order.save()

        # Create unerderlying VM.
        data = serializer.validated_data.pop('vm')
        vm = create_managed_vm(
                order=order,
                cores=data['cores'],
                ram=data['ram_in_gb'],
                disk_size=data['primary_disk']['size_in_gb'],
                image=MatrixServiceProduct.base_image())

        # Create service.
        service = serializer.save(
                order=order,
                owner=request.user,
                vm=vm)

        return Response(serializer.data)

class GenericServiceProductViewSet(ProductViewSet):
    permission_classes = [permissions.IsAuthenticated]

    def get_queryset(self):
        return GenericServiceProduct.objects.filter(owner=self.request.user)

    def get_serializer_class(self):
        if self.action == 'create':
            return OrderGenericServiceProductSerializer
        else:
            return GenericServiceProductSerializer

    @transaction.atomic
    def create(self, request):
        # Extract serializer data.
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        order_recurring_period = serializer.validated_data.pop("recurring_period")
        order_billing_address = serializer.validated_data.pop("billing_address")

        # Create base order.
        order = Order.objects.create(
                recurring_period=order_recurring_period,
                owner=request.user,
                billing_address=order_billing_address,
                starting_date=timezone.now()
                )
        order.save()

        # Create service.
        print(serializer.validated_data)
        service = serializer.save(order=order, owner=request.user)

        # XXX: Move this to some kind of on_create hook in parent
        # Product class?
        order.add_record(
                service.one_time_price,
                service.recurring_price,
                service.description)

        # XXX: Move this to some kind of on_create hook in parent
        # Product class?
        order.add_record(
                service.one_time_price,
                service.recurring_price,
                service.description)

        return Response(serializer.data)