from datetime import timedelta

from django.contrib import admin, messages
from django.contrib.auth.admin import GroupAdmin, UserAdmin
from django.contrib.auth.models import Group, User
from django.db.models import Count, Q
from django.utils import timezone
from django.utils.html import format_html

from .models import ACTIVE_BOOKING_STATUSES, ConsultationRequest, ConsultationSlot


class TeacherAdminSite(admin.AdminSite):
    site_header = "Кабинет преподавателя"
    site_title = "Игорь Безрукавов"
    index_title = "Обзор записей"
    index_template = "admin/index.html"

    def index(self, request, extra_context=None):
        today = timezone.localdate()
        now = timezone.now()
        requests = ConsultationRequest.objects.all()
        extra_context = {
            **(extra_context or {}),
            "dashboard": {
                "new_requests": requests.filter(status=ConsultationRequest.Status.NEW).count(),
                "today_confirmed": requests.filter(
                    status=ConsultationRequest.Status.CONFIRMED, preferred_date=today
                ).count(),
                "upcoming": requests.filter(
                    status__in=ACTIVE_BOOKING_STATUSES,
                    slot__start_at__gte=now,
                ).count(),
                "completed_month": requests.filter(
                    status=ConsultationRequest.Status.COMPLETED,
                    preferred_date__year=today.year,
                    preferred_date__month=today.month,
                ).count(),
            },
            "today": today,
            "next_bookings": requests.filter(
                status__in=ACTIVE_BOOKING_STATUSES,
                slot__start_at__gte=now,
            ).select_related("slot")[:6],
        }
        return super().index(request, extra_context=extra_context)


teacher_admin_site = TeacherAdminSite(name="teacher_admin")
teacher_admin_site.register(User, UserAdmin)
teacher_admin_site.register(Group, GroupAdmin)


@admin.register(ConsultationSlot, site=teacher_admin_site)
class ConsultationSlotAdmin(admin.ModelAdmin):
    list_display = (
        "start_at",
        "duration_minutes",
        "subject",
        "format",
        "booking_state",
        "is_active",
    )
    list_filter = ("subject", "format", "is_active", "start_at")
    search_fields = ("teacher_note",)
    list_editable = ("is_active",)
    date_hierarchy = "start_at"
    ordering = ("start_at",)
    readonly_fields = ("created_at",)
    actions = ("activate_slots", "deactivate_slots", "duplicate_next_week")

    @admin.display(description="Состояние")
    def booking_state(self, slot):
        booking = next(
            (item for item in slot.bookings.all() if item.status in ACTIVE_BOOKING_STATUSES),
            None,
        )
        if booking:
            return format_html('<span class="status-chip status-confirmed">Занято: {}</span>', booking.name)
        if slot.start_at < timezone.now():
            return format_html('<span class="status-chip status-muted">Прошло</span>')
        if not slot.is_active:
            return format_html('<span class="status-chip status-muted">Скрыто</span>')
        return format_html('<span class="status-chip status-new">Свободно</span>')

    def get_queryset(self, request):
        return super().get_queryset(request).prefetch_related("bookings")

    @admin.action(description="Открыть выбранные слоты для записи")
    def activate_slots(self, request, queryset):
        count = queryset.update(is_active=True)
        self.message_user(request, f"Открыто слотов: {count}.", messages.SUCCESS)

    @admin.action(description="Скрыть выбранные слоты с сайта")
    def deactivate_slots(self, request, queryset):
        count = queryset.update(is_active=False)
        self.message_user(request, f"Скрыто слотов: {count}.", messages.SUCCESS)

    @admin.action(description="Создать копии на следующую неделю")
    def duplicate_next_week(self, request, queryset):
        created = 0
        for slot in queryset:
            next_start = slot.start_at + timedelta(days=7)
            if not ConsultationSlot.objects.filter(start_at=next_start).exists():
                ConsultationSlot.objects.create(
                    start_at=next_start,
                    duration_minutes=slot.duration_minutes,
                    subject=slot.subject,
                    format=slot.format,
                    is_active=slot.is_active,
                    teacher_note=slot.teacher_note,
                )
                created += 1
        self.message_user(request, f"Создано слотов: {created}.", messages.SUCCESS)


@admin.register(ConsultationRequest, site=teacher_admin_site)
class ConsultationRequestAdmin(admin.ModelAdmin):
    list_display = (
        "student_name",
        "subject",
        "exam",
        "appointment_time",
        "format",
        "status_badge",
        "contact_details",
    )
    list_filter = ("status", "subject", "exam", "format", "student_grade", "preferred_date", "reminder_sent")
    search_fields = ("name", "phone", "contact", "comment", "teacher_note")
    date_hierarchy = "preferred_date"
    list_select_related = ("slot",)
    readonly_fields = ("created_at", "updated_at", "appointment_summary")
    actions = ("mark_confirmed", "mark_completed", "mark_cancelled", "mark_reminder_sent")
    fieldsets = (
        (
            "Ученик и контакты",
            {
                "fields": (("name", "student_grade"), ("phone", "contact"), "consent_given"),
            },
        ),
        (
            "Запрос",
            {
                "fields": (("subject", "exam", "format"), "comment"),
            },
        ),
        (
            "Время консультации",
            {
                "fields": ("slot", "appointment_summary", ("preferred_date", "preferred_time")),
            },
        ),
        (
            "Работа с заявкой",
            {
                "fields": ("status", "meeting_link", "teacher_note", "cancellation_reason", "reminder_sent"),
            },
        ),
        (
            "Служебные данные",
            {
                "classes": ("collapse",),
                "fields": ("created_at", "updated_at"),
            },
        ),
    )

    @admin.display(description="Ученик", ordering="name")
    def student_name(self, request):
        grade = f", {request.student_grade} класс" if request.student_grade else ""
        return f"{request.name}{grade}"

    @admin.display(description="Консультация", ordering="preferred_date")
    def appointment_time(self, request):
        if not request.preferred_date:
            return "Время не выбрано"
        return f"{request.preferred_date:%d.%m.%Y}, {request.preferred_time:%H:%M}"

    @admin.display(description="Статус", ordering="status")
    def status_badge(self, request):
        classes = {
            ConsultationRequest.Status.NEW: "status-new",
            ConsultationRequest.Status.CONFIRMED: "status-confirmed",
            ConsultationRequest.Status.COMPLETED: "status-completed",
            ConsultationRequest.Status.CANCELLED: "status-cancelled",
            ConsultationRequest.Status.NO_SHOW: "status-muted",
        }
        return format_html(
            '<span class="status-chip {}">{}</span>',
            classes[request.status],
            request.get_status_display(),
        )

    @admin.display(description="Контакты")
    def contact_details(self, request):
        contact = f" · {request.contact}" if request.contact else ""
        return f"{request.phone}{contact}"

    @admin.display(description="Выбранное время")
    def appointment_summary(self, request):
        if request.slot:
            return str(request.slot)
        if request.preferred_date:
            return self.appointment_time(request)
        return "Не выбрано"

    @admin.action(description="Подтвердить выбранные записи")
    def mark_confirmed(self, request, queryset):
        count = queryset.exclude(status=ConsultationRequest.Status.CANCELLED).update(
            status=ConsultationRequest.Status.CONFIRMED
        )
        self.message_user(request, f"Подтверждено записей: {count}.", messages.SUCCESS)

    @admin.action(description="Отметить проведёнными")
    def mark_completed(self, request, queryset):
        count = queryset.update(status=ConsultationRequest.Status.COMPLETED)
        self.message_user(request, f"Проведено консультаций: {count}.", messages.SUCCESS)

    @admin.action(description="Отменить выбранные записи")
    def mark_cancelled(self, request, queryset):
        count = queryset.update(status=ConsultationRequest.Status.CANCELLED)
        self.message_user(request, f"Отменено записей: {count}.", messages.SUCCESS)

    @admin.action(description="Отметить напоминание отправленным")
    def mark_reminder_sent(self, request, queryset):
        count = queryset.update(reminder_sent=True)
        self.message_user(request, f"Напоминание отмечено у записей: {count}.", messages.SUCCESS)
