from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.db.models import Q

from .models import LoginAttempt, User, UserCompanyAccess
from .permissions import accessible_company_ids


@admin.register(User)
class HRPayUserAdmin(UserAdmin):
    """Tenant-aware account administration.

    Superusers may administer all accounts. Other staff users are limited to
    users explicitly linked to one of their companies (or employee profiles in
    one of those companies). This prevents Django Admin from becoming a tenant
    isolation bypass.
    """

    fieldsets = UserAdmin.fieldsets + (
        ("HR-Payroll", {"fields": ("display_name", "force_password_change", "last_password_change_at")}),
    )
    add_fieldsets = UserAdmin.add_fieldsets + (
        ("HR-Payroll", {"fields": ("display_name", "force_password_change")}),
    )
    readonly_fields = tuple(UserAdmin.readonly_fields) + ("last_password_change_at",)
    list_display = UserAdmin.list_display + ("display_name", "force_password_change")

    def get_queryset(self, request):
        qs = super().get_queryset(request)
        if request.user.is_superuser:
            return qs
        company_ids = accessible_company_ids(request.user)
        if not company_ids:
            return qs.none()
        return qs.filter(
            Q(company_accesses__company_id__in=company_ids, company_accesses__is_active=True)
            | Q(employee_profile__company_id__in=company_ids)
            | Q(pk=request.user.pk)
        ).distinct()

    def has_add_permission(self, request):
        # Creating global login identities from tenant-scoped Django Admin can
        # accidentally bypass company assignment. Keep account creation in the
        # controlled application workflow; only the emergency superuser may add here.
        return request.user.is_superuser and super().has_add_permission(request)

    def has_view_permission(self, request, obj=None):
        if request.user.is_superuser or obj is None:
            return super().has_view_permission(request, obj)
        return self.get_queryset(request).filter(pk=obj.pk).exists() and super().has_view_permission(request, obj)

    def has_change_permission(self, request, obj=None):
        if request.user.is_superuser or obj is None:
            return super().has_change_permission(request, obj)
        return self.get_queryset(request).filter(pk=obj.pk).exists() and super().has_change_permission(request, obj)

    def has_delete_permission(self, request, obj=None):
        if request.user.is_superuser or obj is None:
            return super().has_delete_permission(request, obj)
        return self.get_queryset(request).filter(pk=obj.pk).exists() and super().has_delete_permission(request, obj)


@admin.register(UserCompanyAccess)
class UserCompanyAccessAdmin(admin.ModelAdmin):
    list_display = ("user", "company", "is_default", "is_active", "updated_at")
    list_filter = ("is_default", "is_active", "company")
    search_fields = ("user__username", "user__display_name", "company__name")

    def get_queryset(self, request):
        qs = super().get_queryset(request).select_related("user", "company")
        if request.user.is_superuser:
            return qs
        ids = accessible_company_ids(request.user)
        return qs.filter(company_id__in=ids) if ids else qs.none()

    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        if not request.user.is_superuser:
            ids = accessible_company_ids(request.user)
            if db_field.name == "company":
                kwargs["queryset"] = db_field.remote_field.model.objects.filter(pk__in=ids)
            elif db_field.name == "user":
                kwargs["queryset"] = User.objects.filter(
                    Q(company_accesses__company_id__in=ids, company_accesses__is_active=True)
                    | Q(employee_profile__company_id__in=ids)
                    | Q(pk=request.user.pk)
                ).distinct()
        return super().formfield_for_foreignkey(db_field, request, **kwargs)


@admin.register(LoginAttempt)
class LoginAttemptAdmin(admin.ModelAdmin):
    list_display = ("username", "ip_address", "failure_count", "blocked_until", "updated_at")
    search_fields = ("username", "ip_address")
    readonly_fields = ("username", "ip_address", "failure_count", "first_failed_at", "blocked_until", "updated_at")

    # Login attempt rows are not company-keyed. To avoid tenant leakage, only the
    # global emergency superuser can inspect them in Django Admin.
    def has_module_permission(self, request):
        return request.user.is_superuser

    def has_view_permission(self, request, obj=None):
        return request.user.is_superuser

    def has_add_permission(self, request):
        return False

    def has_change_permission(self, request, obj=None):
        return False

    def has_delete_permission(self, request, obj=None):
        return request.user.is_superuser
