from datetime import date

from django.db.models import Exists, OuterRef, Q
from wbcore import filters as wb_filters
from wbportfolio.models import Product

from wbcommission.models import Commission, CommissionRule


def filter_aum(queryset, value):
    return queryset.filter(
        Q(assets_under_management_range__startswith__lte=value)
        & (
            Q(assets_under_management_range__endswith__gt=value)
            | Q(assets_under_management_range__endswith__isnull=True)
        )
        & (Q(percent__gt=0) | Q(consider_zero_percent_for_exclusion=True))
    )


def filter_timestamp(queryset, value):
    return queryset.filter(
        Q(timespan__startswith__lte=value)
        & Q(timespan__endswith__gt=value)
        & (Q(percent__gt=0) | Q(consider_zero_percent_for_exclusion=True))
    )


class CommissionRuleCommissionFilterSet(wb_filters.FilterSet):
    only_valid_at_date = wb_filters.DateFilter(
        required=False,
        initial=lambda f, r, v: date.today(),
        method="filter_only_valid_at_date",
        label="Only Valid at date",
        help_text="Set to show only rules that are valid for the given date",
    )

    def filter_only_valid_at_date(self, queryset, name, value):
        if value:
            return filter_timestamp(queryset, value)
        return queryset

    only_valid_for_aum = wb_filters.NumberFilter(
        required=False,
        method="filter_only_valid_for_aum",
        label="Only Valid for AUM",
        help_text="Set to show only rules that are valid for the given aum",
    )

    def filter_only_valid_for_aum(self, queryset, name, value):
        if value:
            return filter_aum(queryset, value)
        return queryset

    class Meta:
        model = CommissionRule
        fields = {
            "commission": ["exact"],
        }


class CommissionAccountFilterSet(wb_filters.FilterSet):
    only_valid_at_date = wb_filters.DateFilter(
        required=False,
        initial=lambda f, r, v: date.today(),
        method="filter_only_valid_at_date",
        label="Only Valid at date",
        help_text="Set to show only rules that are valid for the given date",
    )

    def filter_only_valid_at_date(self, queryset, name, value):
        if value:
            return queryset.annotate(
                has_valid_rule=Exists(
                    filter_timestamp(CommissionRule.objects.filter(commission=OuterRef("pk")), value)
                )
            ).filter(has_valid_rule=True)

        return queryset

    only_valid_for_aum = wb_filters.NumberFilter(
        required=False,
        method="filter_only_valid_for_aum",
        label="Only Valid for AUM",
        help_text="Set to show only rules that are valid for the given aum",
    )

    def filter_only_valid_for_aum(self, queryset, name, value):
        if value:
            return queryset.annotate(
                has_valid_rule=Exists(filter_aum(CommissionRule.objects.filter(commission=OuterRef("pk")), value))
            ).filter(has_valid_rule=True)

        return queryset

    simulate_for_product = wb_filters.ModelChoiceFilter(
        label="Simulate for Product",
        queryset=Product.objects.all(),
        endpoint=Product.get_representation_endpoint(),
        value_key=Product.get_representation_value_key(),
        label_key=Product.get_representation_label_key(),
        method="fake_filter",
        depends_on=[{"field": "only_valid_at_date", "options": {}}],
        filter_params=lambda request, view: {"with_claim_for_account": view.account.id},
        help_text='Choose a product to compute the actual percent paid for the bellow recipient (need the "Valide at date" filter)',
    )

    class Meta:
        model = Commission
        fields = {}
