"""Advertisers Filters

This module contains Django Filter classes for the advertisers app.
Provides filtering capabilities for API endpoints and list views.

Filters:
    - AgencyFilter: Filter agencies by various criteria
    - BrandFilter: Filter brands by various criteria
    - UserAdvertiserFilter: Filter user-advertiser relationships
"""

import django_filters
from django.db.models import Q
from django.contrib.auth import get_user_model

from .models import Agency, Brand, BrandCategory, UserAdvertiser


User = get_user_model()


class AgencyFilter(django_filters.FilterSet):
    """Filter class for Agency model.
    
    Provides filtering options for agency list views and API endpoints.
    Supports filtering by name, status, location, and date ranges.
    """
    
    # Text search filters
    name = django_filters.CharFilter(
        lookup_expr='icontains',
        help_text="Filter by agency name (case-insensitive)"
    )
    
    search = django_filters.CharFilter(
        method='filter_search',
        help_text="Search across name, description, and contact person"
    )
    
    # Location filters
    city = django_filters.CharFilter(
        lookup_expr='icontains',
        help_text="Filter by city (case-insensitive)"
    )
    
    country = django_filters.CharFilter(
        lookup_expr='icontains',
        help_text="Filter by country (case-insensitive)"
    )
    
    # Status filter
    status = django_filters.ChoiceFilter(
        choices=[('active', 'Active'), ('inactive', 'Inactive')],
        help_text="Filter by agency status"
    )
    
    # Owner filter
    owner = django_filters.ModelChoiceFilter(
        queryset=User.objects.all(),
        help_text="Filter by agency owner"
    )
    
    # Date range filters
    created_after = django_filters.DateFilter(
        field_name='created_at',
        lookup_expr='gte',
        help_text="Filter agencies created after this date (YYYY-MM-DD)"
    )
    
    created_before = django_filters.DateFilter(
        field_name='created_at',
        lookup_expr='lte',
        help_text="Filter agencies created before this date (YYYY-MM-DD)"
    )
    
    # Numeric filters
    min_brands = django_filters.NumberFilter(
        method='filter_min_brands',
        help_text="Filter agencies with at least this many brands"
    )
    
    max_brands = django_filters.NumberFilter(
        method='filter_max_brands',
        help_text="Filter agencies with at most this many brands"
    )
    
    # Boolean filters
    has_website = django_filters.BooleanFilter(
        method='filter_has_website',
        help_text="Filter agencies that have/don't have a website"
    )
    
    has_logo = django_filters.BooleanFilter(
        method='filter_has_logo',
        help_text="Filter agencies that have/don't have a logo"
    )
    
    class Meta:
        model = Agency
        fields = {
            'email': ['exact', 'icontains'],
            'phone': ['exact', 'icontains'],
            'created_at': ['exact', 'gte', 'lte'],
            'updated_at': ['exact', 'gte', 'lte'],
        }
    
    def filter_search(self, queryset, name, value):
        """Filter across multiple text fields."""
        if value:
            return queryset.filter(
                Q(name__icontains=value) |
                Q(description__icontains=value) |
                Q(contact_person__icontains=value) |
                Q(email__icontains=value)
            )
        return queryset
    
    def filter_min_brands(self, queryset, name, value):
        """Filter agencies with minimum number of brands."""
        if value is not None:
            return queryset.annotate(
                brands_count=django_filters.Count('brands')
            ).filter(brands_count__gte=value)
        return queryset
    
    def filter_max_brands(self, queryset, name, value):
        """Filter agencies with maximum number of brands."""
        if value is not None:
            return queryset.annotate(
                brands_count=django_filters.Count('brands')
            ).filter(brands_count__lte=value)
        return queryset
    
    def filter_has_website(self, queryset, name, value):
        """Filter agencies based on website presence."""
        if value is True:
            return queryset.exclude(website__isnull=True).exclude(website='')
        elif value is False:
            return queryset.filter(Q(website__isnull=True) | Q(website=''))
        return queryset
    
    def filter_has_logo(self, queryset, name, value):
        """Filter agencies based on logo presence."""
        if value is True:
            return queryset.exclude(logo__isnull=True).exclude(logo='')
        elif value is False:
            return queryset.filter(Q(logo__isnull=True) | Q(logo=''))
        return queryset


class BrandFilter(django_filters.FilterSet):
    """Filter class for Brand model.
    
    Provides filtering options for brand list views and API endpoints.
    Supports filtering by name, agency, category, industry, and budget ranges.
    """
    
    # Text search filters
    name = django_filters.CharFilter(
        lookup_expr='icontains',
        help_text="Filter by brand name (case-insensitive)"
    )
    
    search = django_filters.CharFilter(
        method='filter_search',
        help_text="Search across name, description, and industry"
    )
    
    # Relationship filters
    agency = django_filters.ModelChoiceFilter(
        queryset=Agency.objects.all(),
        help_text="Filter by agency"
    )
    
    agency_name = django_filters.CharFilter(
        field_name='agency__name',
        lookup_expr='icontains',
        help_text="Filter by agency name (case-insensitive)"
    )
    
    category = django_filters.ModelChoiceFilter(
        queryset=BrandCategory.objects.all(),
        help_text="Filter by brand category"
    )
    
    category_name = django_filters.CharFilter(
        field_name='category__name',
        lookup_expr='icontains',
        help_text="Filter by category name (case-insensitive)"
    )
    
    # Industry filter
    industry = django_filters.CharFilter(
        lookup_expr='icontains',
        help_text="Filter by industry (case-insensitive)"
    )
    
    # Status filter
    status = django_filters.ChoiceFilter(
        choices=[('active', 'Active'), ('inactive', 'Inactive')],
        help_text="Filter by brand status"
    )
    
    # Budget range filters
    min_budget = django_filters.NumberFilter(
        field_name='annual_budget',
        lookup_expr='gte',
        help_text="Filter brands with annual budget >= this amount"
    )
    
    max_budget = django_filters.NumberFilter(
        field_name='annual_budget',
        lookup_expr='lte',
        help_text="Filter brands with annual budget <= this amount"
    )
    
    # Date range filters
    created_after = django_filters.DateFilter(
        field_name='created_at',
        lookup_expr='gte',
        help_text="Filter brands created after this date (YYYY-MM-DD)"
    )
    
    created_before = django_filters.DateFilter(
        field_name='created_at',
        lookup_expr='lte',
        help_text="Filter brands created before this date (YYYY-MM-DD)"
    )
    
    # Campaign-related filters
    has_campaigns = django_filters.BooleanFilter(
        method='filter_has_campaigns',
        help_text="Filter brands that have/don't have campaigns"
    )
    
    min_campaigns = django_filters.NumberFilter(
        method='filter_min_campaigns',
        help_text="Filter brands with at least this many campaigns"
    )
    
    # Boolean filters
    has_logo = django_filters.BooleanFilter(
        method='filter_has_logo',
        help_text="Filter brands that have/don't have a logo"
    )
    
    has_website = django_filters.BooleanFilter(
        method='filter_has_website',
        help_text="Filter brands that have/don't have a website"
    )
    
    class Meta:
        model = Brand
        fields = {
            'contact_email': ['exact', 'icontains'],
            'contact_phone': ['exact', 'icontains'],
            'created_at': ['exact', 'gte', 'lte'],
            'updated_at': ['exact', 'gte', 'lte'],
        }
    
    def filter_search(self, queryset, name, value):
        """Filter across multiple text fields."""
        if value:
            return queryset.filter(
                Q(name__icontains=value) |
                Q(description__icontains=value) |
                Q(industry__icontains=value) |
                Q(target_audience__icontains=value) |
                Q(agency__name__icontains=value)
            )
        return queryset
    
    def filter_has_campaigns(self, queryset, name, value):
        """Filter brands based on campaign presence."""
        if value is True:
            return queryset.filter(campaigns__isnull=False).distinct()
        elif value is False:
            return queryset.filter(campaigns__isnull=True)
        return queryset
    
    def filter_min_campaigns(self, queryset, name, value):
        """Filter brands with minimum number of campaigns."""
        if value is not None:
            return queryset.annotate(
                campaigns_count=django_filters.Count('campaigns')
            ).filter(campaigns_count__gte=value)
        return queryset
    
    def filter_has_logo(self, queryset, name, value):
        """Filter brands based on logo presence."""
        if value is True:
            return queryset.exclude(logo__isnull=True).exclude(logo='')
        elif value is False:
            return queryset.filter(Q(logo__isnull=True) | Q(logo=''))
        return queryset
    
    def filter_has_website(self, queryset, name, value):
        """Filter brands based on website presence."""
        if value is True:
            return queryset.exclude(website__isnull=True).exclude(website='')
        elif value is False:
            return queryset.filter(Q(website__isnull=True) | Q(website=''))
        return queryset


class UserAdvertiserFilter(django_filters.FilterSet):
    """Filter class for UserAdvertiser relationship model.
    
    Provides filtering options for user-advertiser relationships.
    """
    
    # User filters
    user = django_filters.ModelChoiceFilter(
        queryset=User.objects.all(),
        help_text="Filter by user"
    )
    
    user_email = django_filters.CharFilter(
        field_name='user__email',
        lookup_expr='icontains',
        help_text="Filter by user email (case-insensitive)"
    )
    
    # Brand filters
    brand = django_filters.ModelChoiceFilter(
        queryset=Brand.objects.all(),
        help_text="Filter by brand"
    )
    
    brand_name = django_filters.CharFilter(
        field_name='brand__name',
        lookup_expr='icontains',
        help_text="Filter by brand name (case-insensitive)"
    )
    
    # Agency filters
    agency = django_filters.ModelChoiceFilter(
        field_name='brand__agency',
        queryset=Agency.objects.all(),
        help_text="Filter by agency"
    )
    
    agency_name = django_filters.CharFilter(
        field_name='brand__agency__name',
        lookup_expr='icontains',
        help_text="Filter by agency name (case-insensitive)"
    )
    
    # Role filter
    role = django_filters.ChoiceFilter(
        choices=UserAdvertiser.ROLE_CHOICES,
        help_text="Filter by user role"
    )
    
    # Status filter
    is_active = django_filters.BooleanFilter(
        help_text="Filter by active status"
    )
    
    # Date range filters
    created_after = django_filters.DateFilter(
        field_name='created_at',
        lookup_expr='gte',
        help_text="Filter relationships created after this date (YYYY-MM-DD)"
    )
    
    created_before = django_filters.DateFilter(
        field_name='created_at',
        lookup_expr='lte',
        help_text="Filter relationships created before this date (YYYY-MM-DD)"
    )
    
    class Meta:
        model = UserAdvertiser
        fields = {
            'created_at': ['exact', 'gte', 'lte'],
            'updated_at': ['exact', 'gte', 'lte'],
        }


class BrandCategoryFilter(django_filters.FilterSet):
    """Filter class for BrandCategory model.
    
    Provides filtering options for brand categories.
    """
    
    # Text search filters
    name = django_filters.CharFilter(
        lookup_expr='icontains',
        help_text="Filter by category name (case-insensitive)"
    )
    
    search = django_filters.CharFilter(
        method='filter_search',
        help_text="Search across name and description"
    )
    
    # Hierarchy filters
    parent = django_filters.ModelChoiceFilter(
        queryset=BrandCategory.objects.all(),
        help_text="Filter by parent category"
    )
    
    is_root = django_filters.BooleanFilter(
        method='filter_is_root',
        help_text="Filter root categories (no parent)"
    )
    
    has_subcategories = django_filters.BooleanFilter(
        method='filter_has_subcategories',
        help_text="Filter categories that have subcategories"
    )
    
    # Brand count filters
    min_brands = django_filters.NumberFilter(
        method='filter_min_brands',
        help_text="Filter categories with at least this many brands"
    )
    
    class Meta:
        model = BrandCategory
        fields = {
            'created_at': ['exact', 'gte', 'lte'],
            'updated_at': ['exact', 'gte', 'lte'],
        }
    
    def filter_search(self, queryset, name, value):
        """Filter across multiple text fields."""
        if value:
            return queryset.filter(
                Q(name__icontains=value) |
                Q(description__icontains=value)
            )
        return queryset
    
    def filter_is_root(self, queryset, name, value):
        """Filter root categories."""
        if value is True:
            return queryset.filter(parent__isnull=True)
        elif value is False:
            return queryset.filter(parent__isnull=False)
        return queryset
    
    def filter_has_subcategories(self, queryset, name, value):
        """Filter categories with subcategories."""
        if value is True:
            return queryset.filter(subcategories__isnull=False).distinct()
        elif value is False:
            return queryset.filter(subcategories__isnull=True)
        return queryset
    
    def filter_min_brands(self, queryset, name, value):
        """Filter categories with minimum number of brands."""
        if value is not None:
            return queryset.annotate(
                brands_count=django_filters.Count('brands')
            ).filter(brands_count__gte=value)
        return queryset