from django_admin_listfilter_dropdown.filters import RelatedOnlyDropdownFilter
from django_object_actions import DjangoObjectActions, takes_instance_or_queryset
from import_export.admin import ImportExportMixin
from ordered_model.admin import OrderedModelAdmin
from simple_history.admin import SimpleHistoryAdmin

from django import forms
from django.conf import settings
from django.contrib import admin, messages
from django.utils import timezone
from django.utils.html import format_html
from django.utils.translation import gettext_lazy as _

from lms.classrooms.models import StudentSlot
from lms.core.admin.mixins import AddFieldsetsMixin, AddReadonlyFieldsMixin, AdminChangeLinksMixin, CodeMirrorMixin
from lms.courses.models import CourseStudent

from .import_export_resources import (
    EnrollmentTrackerIssueResource, EnrollmentTrackerQueueResource, TicketFieldTemplateResource, TicketTemplateResource,
    TrackerHookEventResource,
)
from .models import (
    ClassroomQueue, ClassroomTracker, EnrolledUserTrackerIssue, EnrollmentQueue, EnrollmentTracker,
    EnrollmentTrackerIssue, EnrollmentTrackerQueue, StudentSlotTrackerIssue, TicketFieldTemplate, TicketTemplate,
    TrackerCourseCategory, TrackerHook, TrackerHookEvent, TrackerIssue, TrackerQueue, TrackerQueueAction,
)
from .services import (
    StartrekError, get_issue_status, process_tracker_hook_event, process_tracker_student_slot_create,
    receive_ticket_status,
)


@admin.register(EnrollmentTrackerQueue)
class EnrollmentTrackerQueueAdmin(ImportExportMixin, OrderedModelAdmin, SimpleHistoryAdmin):
    list_display = ('name', 'display_course', 'is_default')
    list_select_related = (
        # 'enrollment',
        'enrollment__course',
    )
    list_filter = (
        'is_default',
        # ('enrollment', RelatedOnlyDropdownFilter),
        ('enrollment__course', RelatedOnlyDropdownFilter),
    )
    search_fields = ('name',)
    raw_id_fields = ('enrollment',)

    actions = [
        'on_pulling',
        'off_pulling',
    ]

    resource_class = EnrollmentTrackerQueueResource

    def on_pulling(self, request, queryset):
        try:
            queryset.update(tracker_pulling_enabled=True)
            self.message_user(request=request, message=_('Запрос статусов включен'), level=messages.INFO)
        except Exception as exc:
            self.message_user(request=request, message=str(exc), level=messages.ERROR)

    on_pulling.short_description = _("Вкл запрос статусов из Трекера")

    def off_pulling(self, request, queryset):
        try:
            queryset.update(tracker_pulling_enabled=False)
            self.message_user(request=request, message=_('Запрос статусов выключен'), level=messages.INFO)
        except Exception as exc:
            self.message_user(request=request, message=str(exc), level=messages.ERROR)

    off_pulling.short_description = _("Выкл запрос статусов из Трекера")

    def display_course(self, obj: 'EnrollmentTrackerQueue'):
        return obj.enrollment.course

    display_course.short_description = _("Курс")


@admin.register(EnrollmentTrackerIssue)
class EnrollmentTrackerIssueAdmin(
    ImportExportMixin,
    DjangoObjectActions,
    AdminChangeLinksMixin,
    AddFieldsetsMixin,
    AddReadonlyFieldsMixin,
    admin.ModelAdmin
):
    list_display = (
        'display_user', 'display_course', 'display_group',
        'issue_url_link',
        'status', 'status_processed',
        'created', 'modified',
    )
    list_select_related = (
        'enrolled_user__enrollment',
        'enrolled_user__user',
        'enrolled_user__course',
        'enrolled_user__group',
        'queue',
        'queue__enrollment',
    )
    list_filter = (
        'status_processed',
        ('queue', RelatedOnlyDropdownFilter),
        ('enrolled_user__course', RelatedOnlyDropdownFilter),
        ('enrolled_user__group', RelatedOnlyDropdownFilter),
    )
    search_fields = (
        'issue_number',
        'enrolled_user__course__id',
        'enrolled_user__course__name',
        'enrolled_user__user__id',
        'enrolled_user__user__username',
        'enrolled_user__user__yauid',
        'enrolled_user__group__id',
        'enrolled_user__group__name',
    )
    add_readonly_fields = (
        'issue_url_link',
    )
    readonly_fields = add_readonly_fields + (
        'enrolled_user', 'queue', 'issue_number',
        'display_user', 'display_course', 'display_group',
        'display_user_link', 'display_course_link', 'display_group_link',
    )

    add_fieldsets = (
        (None, {'fields': [
            'enrolled_user', 'queue', 'issue_number', 'status',
            'got_status_from_startrek', 'status_processed',
            'issue_url_link'
        ]}),
    )
    fieldsets = (
        (None, {'fields': [
            'enrolled_user_link', 'queue_link', 'issue_url_link',
            'display_user_link', 'display_course_link', 'display_group_link',
            'status', 'got_status_from_startrek', 'status_processed',
        ]}),
    )

    raw_id_fields = ('enrolled_user', 'queue')

    actions = [
        'receive_ticket_status_action',
    ]

    change_actions = [
        'receive_ticket_status_action',
    ]

    change_links = [
        'enrolled_user',
        'queue',
    ]

    resource_class = EnrollmentTrackerIssueResource

    def display_user(self, obj: 'EnrollmentTrackerIssue'):
        return obj.enrolled_user.user

    display_user.short_description = _("Пользователь")

    def display_user_link(self, obj: 'EnrollmentTrackerIssue'):
        return self._get_change_link(obj.enrolled_user, 'user', 'user_link')

    display_user_link.short_description = _("Пользователь")

    def display_course(self, obj: 'EnrollmentTrackerIssue'):
        return obj.enrolled_user.course

    display_course.short_description = _("Курс")

    def display_course_link(self, obj: 'EnrollmentTrackerIssue'):
        return self._get_change_link(obj.enrolled_user, 'course', 'course_link')

    display_course_link.short_description = _("Курс")

    def display_group(self, obj: 'EnrollmentTrackerIssue'):
        return obj.enrolled_user.group

    display_group.short_description = _("Группа")

    def display_group_link(self, obj: 'EnrollmentTrackerIssue'):
        if obj.enrolled_user.group:
            return self._get_change_link(obj.enrolled_user, 'group', 'group_link')

        return '-'

    display_group_link.short_description = _("Группа")

    def issue_url_link(self, obj: 'EnrollmentTrackerIssue'):
        issue = obj.issue
        if issue:
            url = f'{settings.STARTREK_BASE_URL.rstrip("/")}/{issue}'
            return format_html('<a href="{url}" target="_blank">{label}</a>', url=url, label=issue)
        else:
            return ''

    issue_url_link.short_description = 'Тикет в трекере'

    @takes_instance_or_queryset
    def receive_ticket_status_action(self, request, queryset):
        for issue in queryset:
            try:
                receive_ticket_status(issue, force=True)
                message = _(f"Статус тикета {issue.issue} получен")
                level = messages.INFO
            except StartrekError as ex:
                message = str(ex)
                level = messages.ERROR
            self.message_user(
                request=request,
                message=message,
                level=level,
            )

    receive_ticket_status_action.short_description = _("получить статусы тикетов")
    receive_ticket_status_action.label = _("получить статус тикета")


@admin.register(TrackerCourseCategory)
class TrackerCourseCategoryAdmin(admin.ModelAdmin):
    list_display = ('category', 'tracker_course_category_id')
    list_select_related = ('category',)
    raw_id_fields = ('category',)


@admin.register(TrackerHookEvent)
class TrackerHookEventAdmin(ImportExportMixin, DjangoObjectActions, admin.ModelAdmin):
    list_display = ('issue', 'status', 'created', 'modified', 'process_status_result')
    list_select_related = ('issue',)
    raw_id_fields = ('issue',)
    list_filter = ('status',)
    readonly_fields = ('created', 'modified')
    fields = ('issue', 'request_body', 'status', 'process_status_result') + readonly_fields

    actions = [
        "process_tracker_hook_event_action",
    ]

    change_actions = [
        "process_tracker_hook_event_action",
    ]

    search_fields = (
        "issue__issue_number",
    )

    resource_class = TrackerHookEventResource

    def process_tracker_hook_event_action(self, request, queryset):
        for tracker_hook_event in queryset:
            try:
                process_tracker_hook_event(
                    tracker_hook_event=tracker_hook_event,
                    force=True,
                )
                message = _(f"Хук {tracker_hook_event} обработан")
                level = messages.INFO
            except StartrekError as ex:
                message = str(ex)
                level = messages.ERROR

            self.message_user(request, message, level)

    process_tracker_hook_event_action.short_description = _("обработать хуки трекера")
    process_tracker_hook_event_action.label = _("обработать хуки трекера")


@admin.register(TrackerHook)
class TrackerHookAdmin(DjangoObjectActions, admin.ModelAdmin):
    list_display = ("id", "issue", "status", "action", "created", "modified")
    list_select_related = ("issue",)
    raw_id_fields = ("issue",)
    list_filter = ("status", "issue__issue_key")
    readonly_fields = ("action", "created", "modified")
    fields = (
        "issue", "data", "action", "status", "result",
    )

    actions = [
        "process_tracker_hook_action",
    ]

    change_actions = [
        "process_tracker_hook_action",
    ]

    @takes_instance_or_queryset
    def process_tracker_hook_action(self, request, queryset):
        from lms.tracker.services import TrackerHookError, process_tracker_hook

        for tracker_hook in queryset:
            try:
                process_tracker_hook(tracker_hook)
                message = _(f"Событие {tracker_hook} обработано")
                level = messages.INFO

            except TrackerHookError as exc:
                message = str(exc)
                level = messages.ERROR
                tracker_hook.set_error(message)

            self.message_user(request, message, level)

    process_tracker_hook_action.short_description = _("Запустить обновление")
    process_tracker_hook_action.label = _("Запустить обновление")


class TrackerQueueAdminBase(SimpleHistoryAdmin):
    list_display = ('__str__', 'issue_type', 'initial_state', 'template', 'is_active', 'created', 'modified')
    fields = (
        'name', 'display_name', 'issue_type', 'initial_state', 'template', 'is_active',
    )
    search_fields = ("name", "display_name", "issue_type",)


@admin.register(TrackerQueue)
class TrackerQueueAdmin(TrackerQueueAdminBase):
    pass


class GetIssueStatusActionMixin:
    @takes_instance_or_queryset
    def get_issue_status_action(self, request, queryset):
        for obj in queryset:
            tracker_issue = obj.trackerissue_ptr if hasattr(obj, 'trackerissue_ptr') else obj
            try:
                get_issue_status(tracker_issue=tracker_issue)
                message = _(f"Получен статус тикета {tracker_issue.issue_key}")
                level = messages.INFO
            except Exception as exc:
                message = _(f"Ошибка получения статуса тикета {tracker_issue.issue_key} {exc}")
                level = messages.ERROR

            self.message_user(request, message, level)

    get_issue_status_action.short_description = _("Получить статус тикета из трекера")
    get_issue_status_action.label = _("Получить статус тикета из трекера")


@admin.register(TrackerIssue)
class TrackerIssueAdmin(GetIssueStatusActionMixin, DjangoObjectActions, admin.ModelAdmin):
    list_display = ("issue_key", "issue_status", "queue", "queue_type", "status", "created", "modified")
    list_select_related = ("queue",)
    list_filter = (
        ('queue', RelatedOnlyDropdownFilter),
        'status',
    )
    search_fields = ("issue_key", "queue__name")
    raw_id_fields = ("queue",)
    readonly_fields = ("created", "modified")
    fields = (
        "queue_type", "queue", "issue_key", "issue_status", "status",
    ) + readonly_fields

    actions = [
        "get_issue_status_action",
    ]

    change_actions = [
        "get_issue_status_action",
    ]


@admin.register(ClassroomQueue)
class ClassroomQueueAdmin(TrackerQueueAdminBase):
    fields = (
        'name',
        'display_name',
        'issue_type',
        'cancel_transition',
        'cancel_comment',
        'cancel_tags',
        'initial_state',
        'template',
        'is_active',
    )


@admin.register(ClassroomTracker)
class ClassroomTrackerAdmin(DjangoObjectActions, admin.ModelAdmin):
    list_display = ("classroom", "queue", "created", "modified")
    list_select_related = ("classroom", "queue")
    list_filter = (
        ('classroom', RelatedOnlyDropdownFilter),
        ('queue', RelatedOnlyDropdownFilter),
    )
    raw_id_fields = ("classroom", "queue")

    actions = [
        'create_tickets_action',
    ]

    change_actions = [
        'create_tickets_action',
    ]

    @takes_instance_or_queryset
    def create_tickets_action(self, request, queryset):
        student_slots_ids = (
            StudentSlot.objects
            .filter(
                status=StudentSlot.StatusChoices.ACCEPTED,
                timeslot__classroom__tracker__in=queryset,
                timeslot__begin_date__gte=timezone.now(),
                student__status=CourseStudent.StatusChoices.ACTIVE,
            )
            .values_list('id', flat=True)
        )
        for student_slot_id in student_slots_ids:
            try:
                issue = process_tracker_student_slot_create(student_slot_id=student_slot_id)
                if issue:
                    message = _("Тикет создан {key}").format(key=issue.issue_key)
                    level = messages.INFO
                else:
                    message = _("Очередь не настроена")
                    level = messages.WARNING
            except Exception as exc:
                message = str(exc)
                level = messages.ERROR

            self.message_user(request=request, message=message, level=level)

    create_tickets_action.label = _("Создать тикеты")
    create_tickets_action.short_description = _("Создать тикеты")


@admin.register(StudentSlotTrackerIssue)
class StudentSlotTrackerIssueAdmin(GetIssueStatusActionMixin, DjangoObjectActions, admin.ModelAdmin):
    list_display = (
        'slot', 'display_user', 'display_issue_url', 'issue_status', 'queue', 'status',
        'created', 'modified',
    )
    list_select_related = ('slot', 'slot__student__user', 'queue')
    raw_id_fields = ('slot', 'queue')
    readonly_fields = ('queue_type', 'display_user', 'display_issue_url', 'created', 'modified')
    fields = ('slot', 'queue', 'queue_type', 'issue_key', 'issue_status', 'status')
    raw_id_fields = ('slot', 'queue')
    list_filter = (
        # ('slot__student__user', RelatedOnlyDropdownFilter),
        'status',
        'queue_type',
        ('queue', RelatedOnlyDropdownFilter),
    )
    search_fields = ('queue__name', 'slot__student__user__username')

    def display_issue_url(self, obj: StudentSlotTrackerIssue):
        if obj.issue_key:
            return format_html(
                '<a href="{url}/{key}" target="_blank">{key}</a>',
                url=settings.STARTREK_BASE_URL.rstrip("/"),
                key=obj.issue_key,
            )
        else:
            return ''

    display_issue_url.short_description = 'Тикет в трекере'
    display_issue_url.admin_order_field = 'issue_key'

    def display_user(self, obj: StudentSlotTrackerIssue):
        return obj.slot.student.user

    display_user.short_description = _('пользователь')
    display_user.admin_order_field = 'slot__student__user'

    actions = [
        "get_issue_status_action",
    ]

    change_actions = [
        "get_issue_status_action",
    ]


class TicketFieldTemplateAdminForm(forms.ModelForm):
    class Meta:
        model = TicketFieldTemplate
        fields = "__all__"
        widgets = {
            'value': forms.Textarea(attrs={'class': 'codemirror-editor'}),
        }


class TicketFieldTemplateInline(admin.TabularInline):
    form = TicketFieldTemplateAdminForm
    model = TicketFieldTemplate
    fields = ('field_name', 'value', 'allow_null', 'allow_json', 'is_active')
    extra = 0


class TicketTemplateAdminForm(forms.ModelForm):
    class Meta:
        model = TicketTemplate
        fields = "__all__"
        widgets = {
            'summary': forms.Textarea(attrs={'class': 'codemirror-editor'}),
            'description': forms.Textarea(attrs={'class': 'codemirror-editor'}),
        }


@admin.register(TicketTemplate)
class TicketTemplateAdmin(ImportExportMixin, CodeMirrorMixin, SimpleHistoryAdmin):
    form = TicketTemplateAdminForm
    list_display = ('name', 'is_active', 'created', 'modified')
    list_filter = ('is_active',)

    inlines = [
        TicketFieldTemplateInline,
    ]

    resource_class = TicketTemplateResource


@admin.register(TicketFieldTemplate)
class TicketFieldTemplateAdmin(ImportExportMixin, CodeMirrorMixin, admin.ModelAdmin):
    form = TicketFieldTemplateAdminForm
    model = TicketFieldTemplate
    fields = ('field_name', 'value', 'allow_null', 'allow_json', 'is_active')
    resource_class = TicketFieldTemplateResource


@admin.register(EnrollmentQueue)
class EnrollmentQueueAdmin(TrackerQueueAdminBase):
    pass


@admin.register(EnrollmentTracker)
class EnrollmentTrackerAdmin(OrderedModelAdmin):
    list_display = ('enrollment', 'queue', 'is_default', 'created', 'modified')
    list_select_related = ('enrollment', 'queue')
    list_filter = (
        ('enrollment', RelatedOnlyDropdownFilter),
        ('queue', RelatedOnlyDropdownFilter),
    )
    raw_id_fields = ('enrollment', 'queue', 'enrollment_tracker_queue')


@admin.register(EnrolledUserTrackerIssue)
class EnrolledUserTrackerIssueAdmin(GetIssueStatusActionMixin, DjangoObjectActions, admin.ModelAdmin):
    list_display = (
        'enrolled_user', 'display_user', 'display_issue_url', 'issue_status', 'queue', 'status',
        'created', 'modified',
    )
    list_select_related = ('enrolled_user', 'enrolled_user__user', 'queue')
    raw_id_fields = ('enrolled_user', 'queue')
    readonly_fields = ('queue_type', 'display_user', 'display_issue_url', 'created', 'modified')
    fields = (
        'enrolled_user', 'queue', 'queue_type', 'issue_key', 'issue_status', 'status', 'is_default',
        'enrollment_tracker_issue',
    )
    raw_id_fields = ('enrolled_user', 'queue', 'enrollment_tracker_issue')
    list_filter = (
        'status',
        'queue_type',
        ('queue', RelatedOnlyDropdownFilter),
    )
    search_fields = ('queue__name', 'enrolled_user__user__username')

    def display_issue_url(self, obj: EnrolledUserTrackerIssue):
        if obj.issue_key:
            return format_html(
                '<a href="{url}/{key}" target="_blank">{key}</a>',
                url=settings.STARTREK_BASE_URL.rstrip("/"),
                key=obj.issue_key,
            )
        else:
            return ''

    display_issue_url.short_description = 'Тикет в трекере'
    display_issue_url.admin_order_field = 'issue_key'

    def display_user(self, obj: EnrolledUserTrackerIssue):
        return obj.enrolled_user.user

    display_user.short_description = _('пользователь')
    display_user.admin_order_field = 'enrolled_user__user'

    actions = [
        "get_issue_status_action",
    ]

    change_actions = [
        "get_issue_status_action",
    ]


@admin.register(TrackerQueueAction)
class TrackerQueueActionAdmin(admin.ModelAdmin):
    list_display = ('queue', 'action', 'issue_status')
    raw_id_fields = ('queue',)
    list_filter = (
        'action',
        'issue_status',
        ('queue', RelatedOnlyDropdownFilter),
    )
