# crm/views.py

from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth.decorators import login_required
from django.http import JsonResponse
from django.utils import timezone
from .models import Interaction
from .forms import InteractionForm
from farmerapp.models import Farmer, Region, District
from django.db.models import Prefetch

from django.shortcuts import render, get_object_or_404, redirect
from django.contrib.auth.decorators import login_required
from .models import Farmer, Interaction
from .forms import InteractionForm
from django.utils import timezone
from datetime import timedelta
from common.utils import is_supervisor, is_manager
from django.contrib.auth.models import User, Group
from dal import autocomplete
from contacts.models import ContactPerson
from django.db.models import Count, Q
from django.http import HttpResponseForbidden
from django.db.models.functions import Lower


def has_access_to_farmer(user, farmer):
    if is_supervisor(user):
        return True
    elif is_manager(user):
        return farmer.client_status == 'unprocessed' or farmer.interactions.filter(Q(user=user) | Q(assigned_to=user)).exists()
    else:
        return False


@login_required(login_url='accounts/login/')
def create_interaction(request, farmer_id):
    farmer = get_object_or_404(Farmer, id=farmer_id)
    user = request.user

    if not has_access_to_farmer(user, farmer):
        return HttpResponseForbidden("Ви не маєте доступу до цього фермера.")

    if request.method == 'POST':
        form = InteractionForm(request.POST, user=user, farmer=farmer)
        if form.is_valid():
            interaction = form.save(commit=False)
            interaction.user = user
            interaction.farmer = farmer
            interaction.save()
            form.save_m2m()

            # Оновлюємо статус фермерського господарства
            farmer.client_status = interaction.client_status
            farmer.save()

            # Перевіряємо, чи вибрана контактна особа пов'язана з фермером
            contact_person = interaction.contact_person
            if contact_person and not contact_person.farmers.filter(id=farmer.id).exists():
                contact_person.farmers.add(farmer)
                contact_person.save()

            return redirect('farmer_detail', farmer_id=farmer.id)
    else:
        form = InteractionForm(user=user, farmer=farmer)

    interactions = farmer.interactions.all().order_by('-date').prefetch_related('cultures', 'user')

    context = {
        'form': form,
        'farmer': farmer,
        'interactions': interactions,
        'today': timezone.now().date(),
    }

    return render(request, 'crm/create_interaction.html', context)

@login_required
def interaction_list(request):
    # Отримуємо копію параметрів запиту
    query_params = request.GET.copy()

    # Отримуємо параметр сортування
    sort = query_params.get('sort', '-date')  # За замовчуванням сортуємо за датою взаємодії (спаданням)

    # Визначаємо дозволені поля для сортування
    allowed_sort_fields = ['date', '-date', 'next_interaction_date', '-next_interaction_date']

    # Перевіряємо, чи є sort у дозволених полях
    if sort not in allowed_sort_fields:
        sort = '-date'

    # Фільтрація взаємодій
    interactions = Interaction.objects.filter(user=request.user)

    # Фільтрування за статусом клієнта
    client_status = query_params.get('client_status', '')
    if client_status:
        interactions = interactions.filter(client_status=client_status)

    # Фільтрування за фермером
    farmer_id = query_params.get('farmer', '')
    if farmer_id:
        interactions = interactions.filter(farmer__id=farmer_id)

    # Фільтрування за типом взаємодії
    interaction_type = query_params.get('interaction_type', '')
    if interaction_type:
        interactions = interactions.filter(interaction_type=interaction_type)

    # Сортування
    interactions = interactions.order_by(sort)

    # Отримуємо список доступних фермерів для фільтра
    farmers = Farmer.objects.filter(interactions__user=request.user).distinct()

    # Отримуємо список доступних типів взаємодії для фільтра
    interaction_types = Interaction.INTERACTION_TYPES

    # Передаємо параметри до шаблону
    context = {
        'interactions': interactions,
        'current_sort': sort.lstrip('-'),
        'current_sort_direction': 'desc' if sort.startswith('-') else 'asc',
        'client_status': client_status,
        'farmer_id': int(farmer_id) if farmer_id else '',
        'interaction_type': interaction_type,
        'farmers': farmers,
        'interaction_types': interaction_types,
        'query_params': query_params.urlencode(),
    }
    return render(request, 'crm/interaction_list.html', context)


@login_required(login_url='accounts/login/')
def reminders(request):
    upcoming_interactions = Interaction.objects.filter(user=request.user, next_interaction_date__gte=timezone.now()).order_by('next_interaction_date')
    return render(request, 'crm/reminders.html', {'upcoming_interactions': upcoming_interactions})


@login_required(login_url='accounts/login/')
def get_reminders(request):
    current_time = timezone.now()
    reminders = Interaction.objects.filter(user=request.user, next_interaction_date__lte=current_time, next_interaction_date__isnull=False).order_by('next_interaction_date')
    reminders_list = [{
        'farmer': reminder.farmer.name,
        'interaction_type': reminder.get_interaction_type_display(),
        'culture': reminder.culture,
        'price': reminder.price,
        'basis': reminder.basis,
        'comment': reminder.comment,
        'next_interaction_date': reminder.next_interaction_date
    } for reminder in reminders]
    return JsonResponse(reminders_list, safe=False)


@login_required(login_url='accounts/login/')
def user_dashboard(request):
    user = request.user

    if is_manager(user):
        # Менеджер бачить свої власні взаємодії за останні 5 днів
        end_date = timezone.now()
        start_date = end_date - timedelta(days=5)

        interactions = Interaction.objects.filter(
            user=user,
            date__range=(start_date, end_date)
        ).select_related('farmer').prefetch_related('cultures')

        context = {
            'interactions': interactions,
        }
        return render(request, 'crm/manager_dashboard.html', context)

    elif is_supervisor(user):
        # Отримуємо параметри фільтрації та сортування з GET-запиту
        period = request.GET.get('period', 'all')  # За замовчуванням 'all' - весь період
        sort_order = request.GET.get('sort_order', 'desc')  # За замовчуванням 'desc' - за спаданням

        # Визначаємо початкову та кінцеву дати на основі обраного періоду
        end_date = timezone.now()
        start_date = None  # За замовчуванням немає фільтра за датою

        if period == 'week':
            start_date = end_date - timedelta(weeks=1)
        elif period == 'month':
            start_date = end_date - timedelta(days=30)
        elif period == '3months':
            start_date = end_date - timedelta(days=90)
        elif period == '6months':
            start_date = end_date - timedelta(days=180)
        elif period == 'year':
            start_date = end_date - timedelta(days=365)
        elif period == 'all':
            start_date = None  # Немає фільтрації за датою

        # Отримуємо групи "Managers" та "Supervisors"
        manager_group = Group.objects.get(name='Managers')
        supervisor_group = Group.objects.get(name='Supervisors')

        # Отримуємо всіх користувачів з цих груп
        managers = User.objects.filter(Q(groups=manager_group) | Q(groups=supervisor_group)).distinct()

        # Отримуємо всі взаємодії, створені цими користувачами
        interactions = Interaction.objects.filter(
            user__in=managers,
        ).select_related('farmer', 'user').prefetch_related('cultures')

        # Застосовуємо фільтрацію за датою, якщо потрібно
        if start_date:
            interactions = interactions.filter(date__range=(start_date, end_date))

        # Статистика по менеджерах
        stats = []
        possible_statuses = [choice[0] for choice in Interaction.CLIENT_STATUS_CHOICES]
        status_display_names = {choice[0]: choice[1] for choice in Interaction.CLIENT_STATUS_CHOICES}

        for manager in managers:
            manager_interactions = interactions.filter(user=manager)
            total_interactions = manager_interactions.count()
            status_counts = manager_interactions.values('client_status').annotate(count=Count('client_status'))

            # Перетворюємо статуси у словник для зручності доступу в шаблоні
            status_counts_dict = {status: 0 for status in possible_statuses}
            for item in status_counts:
                status = item['client_status']
                count = item['count']
                status_counts_dict[status] = count

            stats.append({
                'manager': manager,
                'total_interactions': total_interactions,
                'status_counts': status_counts_dict,
            })

        # Сортуємо статистику за кількістю взаємодій
        reverse = True if sort_order == 'desc' else False
        stats = sorted(stats, key=lambda x: x['total_interactions'], reverse=reverse)

        # Словник для вибору періоду
        PERIOD_CHOICES = {
            'all': 'За весь період',
            'week': 'За тиждень',
            'month': 'За місяць',
            '3months': 'За 3 місяці',
            '6months': 'За пів-року',
            'year': 'За рік',
        }

        context = {
            'interactions': interactions,
            'stats': stats,
            'period': period,
            'sort_order': sort_order,
            'possible_statuses': possible_statuses,
            'status_display_names': status_display_names,
            'PERIOD_CHOICES': PERIOD_CHOICES,
        }
        return render(request, 'crm/supervisor_dashboard.html', context)

    else:
        return HttpResponseForbidden("Ви не маєте доступу до цієї сторінки.")


@login_required(login_url='accounts/login/')
def user_interactions(request, user_id):
    user = request.user

    if not is_supervisor(user):
        return HttpResponseForbidden("Ви не маєте доступу до цієї сторінки.")

    # Отримуємо користувача, взаємодії якого хочемо переглянути
    target_user = get_object_or_404(User, id=user_id)

    # Перевіряємо, чи користувач належить до групи "Managers" або "Supervisors"
    manager_group = Group.objects.get(name='Managers')
    supervisor_group = Group.objects.get(name='Supervisors')
    if not target_user.groups.filter(Q(id=manager_group.id) | Q(id=supervisor_group.id)).exists():
        return HttpResponseForbidden("Ви не можете переглядати взаємодії цього користувача.")

    # Отримуємо параметр періоду з GET-запиту
    period = request.GET.get('period', 'all')  # За замовчуванням 'all' - весь період

    # Визначаємо початкову та кінцеву дати на основі обраного періоду
    end_date = timezone.now()
    start_date = None  # За замовчуванням немає фільтра за датою

    if period == 'week':
        start_date = end_date - timedelta(weeks=1)
    elif period == 'month':
        start_date = end_date - timedelta(days=30)
    elif period == '3months':
        start_date = end_date - timedelta(days=90)
    elif period == '6months':
        start_date = end_date - timedelta(days=180)
    elif period == 'year':
        start_date = end_date - timedelta(days=365)
    elif period == 'all':
        start_date = None  # Немає фільтрації за датою

    # Отримуємо взаємодії, створені цим користувачем
    interactions = Interaction.objects.filter(
        user=target_user,
    ).select_related('farmer', 'user').prefetch_related('cultures')

    # Застосовуємо фільтрацію за датою, якщо потрібно
    if start_date:
        interactions = interactions.filter(date__range=(start_date, end_date))

    # Словник для вибору періоду
    PERIOD_CHOICES = {
        'all': 'За весь період',
        'week': 'За тиждень',
        'month': 'За місяць',
        '3months': 'За 3 місяці',
        '6months': 'За пів-року',
        'year': 'За рік',
    }

    context = {
        'interactions': interactions,
        'target_user': target_user,
        'period': period,
        'PERIOD_CHOICES': PERIOD_CHOICES,
    }

    return render(request, 'crm/user_interactions.html', context)


@login_required(login_url='accounts/login/')
def region_statistics(request):
    user = request.user

    # Визначаємо доступних фермерів залежно від ролі користувача
    if is_supervisor(user):
        farmers = Farmer.objects.all()
    elif is_manager(user):
        farmers = Farmer.objects.filter(
            Q(client_status='unprocessed') |
            Q(interactions__user=user)
        ).distinct()
    else:
        return HttpResponseForbidden("Ви не маєте доступу до цієї сторінки.")

    # Отримуємо можливі статуси
    CLIENT_STATUS_CHOICES = Farmer.CLIENT_STATUS_CHOICES
    possible_statuses = [choice[0] for choice in CLIENT_STATUS_CHOICES]
    status_display_names = {choice[0]: choice[1] for choice in CLIENT_STATUS_CHOICES}

    # Групуємо фермерів за регіонами та анотуємо потрібні значення
    regions = farmers.values('region__id', 'region__name').annotate(
        num_farms=Count('id'),
        num_interactions=Count('interactions', distinct=True),
        **{
            f'num_{status}': Count('id', filter=Q(client_status=status))
            for status in possible_statuses
        }
    ).order_by('region__name')

    # Обчислюємо загальні суми
    total_num_farms = 0
    total_num_interactions = 0
    total_num_statuses = {status: 0 for status in possible_statuses}

    for region in regions:
        total_num_farms += region['num_farms']
        total_num_interactions += region['num_interactions']
        for status in possible_statuses:
            total_num_statuses[status] += region.get(f'num_{status}', 0)

    context = {
        'regions': regions,
        'possible_statuses': possible_statuses,
        'status_display_names': status_display_names,
        'total_num_farms': total_num_farms,
        'total_num_interactions': total_num_interactions,
        'total_num_statuses': total_num_statuses,
    }

    return render(request, 'crm/region_statistics.html', context)


@login_required(login_url='accounts/login/')
def district_statistics(request, region_id):
    user = request.user

    # Отримуємо область або повертаємо 404, якщо не знайдено
    region = get_object_or_404(Region, id=region_id)

    # Визначаємо доступних фермерів залежно від ролі користувача
    if is_supervisor(user):
        farmers = Farmer.objects.filter(region=region)
    elif is_manager(user):
        farmers = Farmer.objects.filter(
            Q(client_status='unprocessed') |
            Q(interactions__user=user),
            region=region  # Іменований аргумент після позиційних
        ).distinct()
    else:
        return HttpResponseForbidden("Ви не маєте доступу до цієї сторінки.")

    # Отримуємо можливі статуси
    CLIENT_STATUS_CHOICES = Farmer.CLIENT_STATUS_CHOICES
    possible_statuses = [choice[0] for choice in CLIENT_STATUS_CHOICES]
    status_display_names = {choice[0]: choice[1] for choice in CLIENT_STATUS_CHOICES}

    # Групуємо фермерів за районами та анотуємо потрібні значення
    districts = farmers.values('district__id', 'district__name').annotate(
        num_farms=Count('id'),
        num_interactions=Count('interactions', distinct=True),
        **{
            f'num_{status}': Count('id', filter=Q(client_status=status))
            for status in possible_statuses
        }
    ).order_by('district__name')

    # Обчислюємо загальні суми
    total_num_farms = 0
    total_num_interactions = 0
    total_num_statuses = {status: 0 for status in possible_statuses}

    for district in districts:
        total_num_farms += district['num_farms']
        total_num_interactions += district['num_interactions']
        for status in possible_statuses:
            total_num_statuses[status] += district.get(f'num_{status}', 0)

    context = {
        'region': region,
        'districts': districts,
        'possible_statuses': possible_statuses,
        'status_display_names': status_display_names,
        'total_num_farms': total_num_farms,
        'total_num_interactions': total_num_interactions,
        'total_num_statuses': total_num_statuses,
    }

    return render(request, 'crm/district_statistics.html', context)


class ContactPersonAutocomplete(autocomplete.Select2QuerySetView):
    def get_queryset(self):
        if not self.request.user.is_authenticated:
            return ContactPerson.objects.none()

        qs = ContactPerson.objects.all()

        farmer_id = self.forwarded.get('farmer', None)
        if farmer_id:
            qs = qs.filter(
                Q(farmers__id=farmer_id) | Q(farmers__isnull=True)
            ).distinct()

        if self.q:
            search_term = self.q
            qs = qs.filter(
                Q(name__icontains=search_term) |
                Q(surname__icontains=search_term) |
                Q(father_name__icontains=search_term)
            )

        return qs

    def get_result_label(self, item):
        return f"{item.surname} {item.name} {item.father_name}"