import datetime

from rest_framework import filters


def _parse_date(value):
    try:
        return datetime.date.fromisoformat(value)
    except (TypeError, ValueError):
        return None


class DateRangeFilter(filters.BaseFilterBackend):
    """`?date_from=YYYY-MM-DD&date_to=YYYY-MM-DD` (both inclusive).

    The view names the column via `date_field` (defaults to `created_at`); a DateTimeField
    is compared by calendar date in the active time zone.
    """

    def filter_queryset(self, request, queryset, view):
        field = getattr(view, 'date_field', None)
        if not field:
            return queryset
        date_from = _parse_date(request.query_params.get('date_from'))
        date_to = _parse_date(request.query_params.get('date_to'))
        is_datetime = queryset.model._meta.get_field(field).get_internal_type() == 'DateTimeField'
        lookup = f'{field}__date' if is_datetime else field
        if date_from:
            queryset = queryset.filter(**{f'{lookup}__gte': date_from})
        if date_to:
            queryset = queryset.filter(**{f'{lookup}__lte': date_to})
        return queryset


class QueryParamFilter(filters.BaseFilterBackend):
    """Exact-match filters declared on the view: `query_filters = {'param': 'orm__lookup'}`.

    Boolean-looking values ('true'/'false') are coerced for BooleanField lookups.
    """

    def filter_queryset(self, request, queryset, view):
        mapping = getattr(view, 'query_filters', None) or {}
        for param, lookup in mapping.items():
            value = request.query_params.get(param)
            if value in (None, ''):
                continue
            if value.lower() in ('true', 'false') and param.startswith('is_'):
                value = value.lower() == 'true'
            queryset = queryset.filter(**{lookup: value})
        return queryset
