from django_filters import rest_framework as filters
from .models import (
    Products,
    ProductGallery,
    NewsGallery,
    Catalogs,
    Categories,
    Series,
    NewsAndPressReleases,
)
from datetime import datetime
from django.db.models import Q
from utils.utils import BaseFilterWithArchiveFilter


class CatalogsFilter(BaseFilterWithArchiveFilter):
    title = filters.CharFilter(field_name="title", lookup_expr="icontains")

    class Meta:
        model = Catalogs
        fields = ["title"]


class CategoriesFilter(BaseFilterWithArchiveFilter):
    search = filters.CharFilter(method="filter_by_search", label="Search")
    is_active = filters.BooleanFilter(field_name="is_active")

    class Meta:
        model = Categories
        fields = ["search", "is_active"]

    def filter_by_search(self, queryset, name, value):
        queryset = queryset.filter(
            Q(main_category_name__icontains=value)
            | Q(sub_category_name__icontains=value)
        )
        return queryset


class SeriesFilter(BaseFilterWithArchiveFilter):
    name = filters.CharFilter(field_name="name", lookup_expr="icontains")
    is_active = filters.BooleanFilter(field_name="is_active")

    class Meta:
        model = Series
        fields = ["name", "is_active"]


class ProductsFilter(BaseFilterWithArchiveFilter):
    search = filters.CharFilter(method="filter_by_search", label="Search")
    name = filters.CharFilter(field_name="name", lookup_expr="icontains")
    description = filters.CharFilter(field_name="description", lookup_expr="icontains")
    edp_number = filters.CharFilter(field_name="edp_number", lookup_expr="icontains")
    article_number = filters.CharFilter(
        field_name="article_number", lookup_expr="icontains"
    )
    finish = filters.CharFilter(field_name="finish", lookup_expr="icontains")
    size = filters.CharFilter(field_name="size", lookup_expr="icontains")
    main_category = filters.CharFilter(
        method="filter_by_main_category", label="Multiple Filter by Main Category name"
    )
    sub_category = filters.CharFilter(
        field_name="category__sub_category_name", lookup_expr="iexact"
    )
    series = filters.CharFilter(field_name="series__name", lookup_expr="iexact")
    is_active = filters.BooleanFilter(field_name="is_active")
    is_sold_as_set = filters.BooleanFilter(field_name="sold_as_set")
    is_discounted = filters.BooleanFilter(field_name="is_discounted")
    is_coming_soon = filters.BooleanFilter(field_name="is_coming_soon")
    is_new_arrival = filters.BooleanFilter(field_name="is_new_arrival")
    quantity = filters.NumberFilter(field_name="quantity")
    start_price = filters.CharFilter(
        method="filter_by_start_price", label="Start Price"
    )
    end_price = filters.CharFilter(method="filter_by_end_price", label="End Price")
    start_arrival_date = filters.DateFilter(
        method="filter_by_start_arrival_date", label="Start Arrival Date"
    )
    end_arrival_date = filters.DateFilter(
        method="filter_by_end_arrival_date", label="End Arrival Date"
    )
    sort_by = filters.CharFilter(method="sort_by_value", label="Sort By")

    class Meta:
        model = Products
        fields = [
            "search",
            "name",
            "description",
            "edp_number",
            "article_number",
            "finish",
            "size",
            "main_category",
            "sub_category",
            "series",
            "is_active",
            "is_sold_as_set",
            "is_discounted",
            "is_new_arrival",
            "is_coming_soon",
            "quantity",
            "start_price",
            "end_price",
            "start_arrival_date",
            "end_arrival_date",
            "sort_by",
        ]

    def filter_by_search(self, queryset, name, value):
        return queryset.filter(
            Q(name__icontains=value)
            | Q(edp_number__icontains=value)
            | Q(article_number__icontains=value)
            | Q(finish__icontains=value)
            | Q(size__icontains=value)
            | Q(series__name__icontains=value)
            | Q(category__main_category_name__icontains=value)
            | Q(category__sub_category_name__icontains=value)
        )

    def filter_by_start_price(self, queryset, name, value):
        float_value = float(value)
        return queryset.filter(price__gte=float_value)

    def filter_by_end_price(self, queryset, name, value):
        float_value = float(value)
        return queryset.filter(price__lte=float_value)

    def sort_by_value(self, queryset, name, value):
        value = value.lower()

        if value == "a-z":
            return queryset.order_by("name")

        if value == "z-a":
            return queryset.order_by("-name")

        if value == "oldest":
            return queryset.order_by("arrival_date")

        if value == "newest":
            return queryset.order_by("-arrival_date")

        if value == "price: low to high":
            return queryset.order_by("price").exclude(price=0.00)

        if value == "price: high to low":
            return queryset.order_by("-price").exclude(price=0.00)

        return queryset  # pragma: no cover

    def filter_by_main_category(self, queryset, name, value):
        return queryset.filter(category__main_category_name__overlap=[value.title()])

        # If filter is multiple, use this code block
        # if value == "," or value in ["", " ", None, "null"]:
        #     return queryset.none()
        # else:
        #     arr_value = value.split(",")

    def filter_by_start_arrival_date(self, queryset, name, value):
        date_value = datetime.strptime(str(value), "%Y-%m-%d").date()
        return queryset.filter(arrival_date__date__gte=date_value)

    def filter_by_end_arrival_date(self, queryset, name, value):
        date_value = datetime.strptime(str(value), "%Y-%m-%d").date()
        return queryset.filter(arrival_date__date__lte=date_value)


class ProductGalleryFilter(filters.FilterSet):
    product_id = filters.CharFilter(field_name="product__id", lookup_expr="exact")
    product_name = filters.CharFilter(field_name="product__name", lookup_expr="iexact")
    edp_number = filters.CharFilter(
        field_name="product__edp_number", lookup_expr="exact"
    )
    article_number = filters.CharFilter(
        field_name="product__article_number", lookup_expr="exact"
    )

    class Meta:
        model = ProductGallery
        fields = [
            "product_id",
            "product_name",
            "edp_number",
            "article_number",
        ]


class NewsGalleryFilter(filters.FilterSet):
    news_id = filters.CharFilter(field_name="news__id", lookup_expr="exact")
    news_title = filters.CharFilter(field_name="news__title", lookup_expr="icontains")

    class Meta:
        model = NewsGallery
        fields = [
            "news_id",
            "news_title",
        ]


class NewsAndPressReleasesFilter(BaseFilterWithArchiveFilter):
    type = filters.CharFilter(field_name="type", lookup_expr="exact")
    title = filters.CharFilter(field_name="title", lookup_expr="icontains")

    class Meta:
        model = NewsAndPressReleases
        fields = ["type", "title"]
