"""
Form mixins for tenant-aware forms.

Provides mixins to handle hospital field visibility based on user role.
"""

from django import forms
from apps.organizations.models import Hospital


class HospitalFieldMixin:
    """
    Mixin to handle hospital field - always hidden, auto-set based on user context.

    - PX Admins: Hidden field, auto-set from session (request.tenant_hospital)
    - Others: Hidden field, auto-set from user's hospital (User.hospital)

    Usage:
        class MyForm(HospitalFieldMixin, forms.ModelForm):
            class Meta:
                model = MyModel
                fields = ['hospital', ...]

            def __init__(self, *args, **kwargs):
                super().__init__(*args, **kwargs)
                # Hospital field is automatically configured

    In views:
        form = MyForm(request=request)
    """

    def __init__(self, *args, **kwargs):
        self.request = kwargs.pop("request", None)
        self.user = kwargs.pop("user", None) or (self.request.user if self.request else None)
        super().__init__(*args, **kwargs)

        if self.user and "hospital" in self.fields:
            self._setup_hospital_field()

    def _setup_hospital_field(self):
        """Configure hospital field - always hidden, auto-set based on user context."""
        hospital_field = self.fields["hospital"]

        hospital_field.widget = forms.HiddenInput()
        hospital_field.required = False

        hospital = None

        if self.user.is_px_admin():
            hospital = getattr(self.request, "tenant_hospital", None)
        else:
            hospital = self.user.hospital

        if hospital:
            hospital_field.initial = hospital
            hospital_field.queryset = Hospital.objects.filter(id=hospital.id)
        else:
            hospital_field.queryset = Hospital.objects.none()

    def clean_hospital(self):
        """
        Auto-set hospital based on user context.
        """
        hospital = self.cleaned_data.get("hospital")

        if not self.user:
            return hospital

        if self.user.is_px_admin():
            hospital = getattr(self.request, "tenant_hospital", None)
            if not hospital:
                raise forms.ValidationError("No hospital selected. Please select a hospital first.")
            return hospital
        else:
            if self.user.hospital:
                return self.user.hospital
            else:
                raise forms.ValidationError("You do not have a hospital assigned. Please contact your administrator.")


class DepartmentFieldMixin:
    """
    Mixin to handle department field filtering based on user's hospital.

    - Filters departments to only show those in the selected/current hospital
    - Works with HospitalFieldMixin

    Usage:
        class MyForm(HospitalFieldMixin, DepartmentFieldMixin, forms.ModelForm):
            class Meta:
                model = MyModel
                fields = ['hospital', 'department', ...]
    """

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        if "department" in self.fields:
            self._setup_department_field()

    def _setup_department_field(self):
        """Configure department field with hospital-based filtering."""
        from apps.organizations.models import Department

        department_field = self.fields["department"]

        # Get the hospital (either from form data or user's hospital)
        hospital = None
        if self.data.get("hospital"):
            try:
                hospital = Hospital.objects.get(id=self.data["hospital"])
            except Hospital.DoesNotExist:
                pass
        elif self.initial.get("hospital"):
            hospital = self.initial["hospital"]
        elif self.instance and self.instance.pk:
            # Only access hospital if instance is saved (has pk)
            try:
                hospital = self.instance.hospital
            except Exception:
                # Hospital not set (RelatedObjectDoesNotExist or similar)
                pass
        elif self.user and self.user.is_px_admin():
            hospital = getattr(self.request, "tenant_hospital", None)
        elif self.user and self.user.hospital:
            hospital = self.user.hospital

        if hospital:
            # Filter departments to user's hospital
            department_field.queryset = Department.objects.filter(hospital=hospital, status="active").order_by("name")
        else:
            # No hospital context - empty queryset
            department_field.queryset = Department.objects.none()
