from django.shortcuts import render
from django.conf import settings
from django.contrib.auth.models import User

from rest_framework import generics
from django_filters import rest_framework as filters
from rest_framework.schemas.openapi import AutoSchema

from .models import DataProduct, DataProductFilter, DataLocation, WorkSpecification, ATDBProcessingSite
from .serializers import DataProductSerializer, \
    DataProductFlatSerializer, DataLocationSerializer, \
    WorkSpecificationSerializer


class DynamicFilterSet(filters.FilterSet):
    class Meta:
        filter_class = None

    def __init__(self, *args, **kwargs):
        self._load_filters()
        super().__init__(*args, **kwargs)

    def _load_filters(self):
        if self.Meta.filter_class is None:
            raise Exception('Define filter_class meta attribute')
        for item in self.Meta.filter_class.objects.all():
            field_obj = self.Meta.model._meta.get_field(item.field)
            filter_class, *_ = self.filter_for_lookup(field_obj, item.lookup_type)
            self.base_filters[item.name] = filter_class(item.field)


# --- Filters ---
class DataProductFilterSet(DynamicFilterSet):
    class Meta:
        model = DataProduct
        filter_class = DataProductFilter
        fields = {
            'obs_id': ['exact', 'icontains'],
        }


# ---------- GUI Views -----------

def index(request):
    atdb_hosts = ATDBProcessingSite.objects.values('name', 'url')
    return render(request, "lofardata/index.html", {'atdb_hosts': atdb_hosts})


# ---------- REST API views ----------
class DataProductView(generics.ListCreateAPIView):
    model = DataProduct
    serializer_class = DataProductSerializer

    queryset = DataProduct.objects.all().order_by('obs_id')

    # using the Django Filter Backend - https://django-filter.readthedocs.io/en/latest/index.html
    filter_backends = (filters.DjangoFilterBackend,)
    filter_class = DataProductFilterSet


class DataProductDetailsView(generics.RetrieveUpdateDestroyAPIView):
    model = DataProduct
    serializer_class = DataProductSerializer
    queryset = DataProduct.objects.all()


class DataLocationView(generics.ListCreateAPIView):
    model = DataLocation
    serializer_class = DataLocationSerializer
    queryset = DataLocation.objects.all().order_by('name')


class InsertWorkSpecificationSchema(AutoSchema):
    def get_operation_id_base(self, path, method, action):
        return 'createDataProductMulti'


class InsertMultiDataproductView(generics.CreateAPIView):
    """
    Add single DataProduct
    """
    queryset = DataProduct.objects.all()
    serializer_class = DataProductFlatSerializer
    schema = InsertWorkSpecificationSchema()

    def get_serializer(self, *args, **kwargs):
        """ if an array is passed, set serializer to many """
        if isinstance(kwargs.get('data', {}), list):
            kwargs['many'] = True
        return super().get_serializer(*args, **kwargs)


class InsertWorkSpecification(generics.CreateAPIView, generics.ListCreateAPIView):
    queryset = WorkSpecification.objects.all()
    serializer_class = WorkSpecificationSerializer

    def get_queryset(self):
        current_user: User = self.request.user
        if not current_user.is_staff or not current_user.is_superuser:
            return self.queryset.filter(created_by=current_user.id)
        else:
            return self.queryset