"""
Observations forms - Public and internal forms for observation management.
"""

from django import forms
from django.core.validators import FileExtensionValidator
from django.utils import timezone
from django.utils.translation import gettext_lazy as _

from apps.accounts.models import User
from apps.organizations.models import Department

from .models import (
    Observation,
    ObservationAttachment,
    ObservationCategory,
    ObservationNote,
    ObservationSeverity,
    ObservationStatus,
    ObservationSubCategory,
)


# Allowed file extensions for attachments
ALLOWED_EXTENSIONS = ["jpg", "jpeg", "png", "gif", "pdf", "doc", "docx", "xls", "xlsx"]
MAX_FILE_SIZE = 10 * 1024 * 1024  # 10 MB


class ObservationPublicForm(forms.ModelForm):
    """
    Public form for submitting observations.

    Features:
    - No login required
    - Optional reporter information
    - Honeypot field for spam protection
    - File attachments support
    """

    # Honeypot field for spam protection
    website = forms.CharField(
        required=False,
        widget=forms.TextInput(
            attrs={
                "style": "display:none !important;",
                "tabindex": "-1",
                "autocomplete": "off",
            }
        ),
        label="",
    )

    # File attachments (handled separately in the view)
    # Note: Multiple file upload is handled via HTML attribute and view processing
    attachments = forms.FileField(
        required=False,
        widget=forms.FileInput(
            attrs={
                "accept": ".jpg,.jpeg,.png,.gif,.pdf,.doc,.docx,.xls,.xlsx",
                "class": "form-control",
            }
        ),
        help_text="Upload a file (max 10MB). Allowed: images, PDF, Word, Excel.",
    )

    class Meta:
        model = Observation
        fields = [
            "hospital",
            "category",
            "title",
            "description",
            "location_text",
            "incident_datetime",
            "reporter_staff_id",
            "reporter_name",
            "reporter_phone",
            "reporter_email",
        ]
        widgets = {
            "category": forms.Select(
                attrs={
                    "class": "form-select",
                }
            ),
            "title": forms.TextInput(
                attrs={
                    "class": "form-control",
                    "placeholder": "Brief title (optional)",
                }
            ),
            "description": forms.Textarea(
                attrs={
                    "class": "form-control",
                    "rows": 5,
                    "placeholder": "Please describe what you observed in detail...",
                }
            ),
            "location_text": forms.TextInput(
                attrs={
                    "class": "form-control",
                    "placeholder": "e.g., Building A, Floor 2, Room 205",
                }
            ),
            "incident_datetime": forms.DateTimeInput(
                attrs={
                    "class": "form-control",
                    "type": "datetime-local",
                }
            ),
            "reporter_staff_id": forms.TextInput(
                attrs={
                    "class": "form-control",
                    "placeholder": "Your staff ID (optional)",
                }
            ),
            "reporter_name": forms.TextInput(
                attrs={
                    "class": "form-control",
                    "placeholder": "Your name (optional)",
                }
            ),
            "reporter_phone": forms.TextInput(
                attrs={
                    "class": "form-control",
                    "placeholder": "Your phone number (optional)",
                }
            ),
            "reporter_email": forms.EmailInput(
                attrs={
                    "class": "form-control",
                    "placeholder": "Your email (optional)",
                }
            ),
        }

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

        # Only show active categories
        self.fields["category"].queryset = ObservationCategory.objects.filter(is_active=True).order_by(
            "sort_order", "name_en"
        )
        self.fields["category"].empty_label = "Select a category (optional)"

        # Set default incident datetime to now
        if not self.instance.pk:
            self.initial["incident_datetime"] = timezone.now().strftime("%Y-%m-%dT%H:%M")

    def clean_website(self):
        """Honeypot validation - should be empty."""
        website = self.cleaned_data.get("website")
        if website:
            raise forms.ValidationError("Spam detected.")
        return website

    def clean_description(self):
        """Validate description is not too short."""
        description = self.cleaned_data.get("description", "")
        if len(description.strip()) < 10:
            raise forms.ValidationError("Please provide a more detailed description (at least 10 characters).")
        return description


class ObservationInternalForm(forms.ModelForm):
    """
    Internal form for authenticated staff to create observations.

    Differences from ObservationPublicForm:
    - No honeypot field (authenticated users)
    - No reporter fields (auto-filled from request.user)
    - Includes assignment fields (department, assignee)
    - Source field for PXSource selection
    """

    attachments = forms.FileField(
        required=False,
        widget=forms.FileInput(
            attrs={
                "accept": ".jpg,.jpeg,.png,.gif,.pdf,.doc,.docx,.xls,.xlsx",
                "class": "form-control",
            }
        ),
        help_text="Upload files (max 10MB each). Allowed: images, PDF, Word, Excel.",
    )

    description_en = forms.CharField(
        required=False,
        widget=forms.Textarea(attrs={"class": "form-control", "rows": 5, "placeholder": "English description of the observation..."}),
        help_text="Full English version of the observation description.",
    )

    class Meta:
        model = Observation
        fields = [
            "category",
            "sub_category",
            "title",
            "description",
            "description_en",
            "location_text",
            "location",
            "main_section",
            "subsection",
            "incident_datetime",
            "patient_file_number",
            "assigned_department",
            "assigned_to",
            "person_noted",
            "department_noted",
            "communication_method",
            "communication_datetime",
            "px_source",
        ]
        widgets = {
            "category": forms.Select(
                attrs={
                    "class": "form-select",
                }
            ),
            "sub_category": forms.Select(
                attrs={
                    "class": "form-select",
                }
            ),
            "title": forms.TextInput(
                attrs={
                    "class": "form-control",
                    "placeholder": "Brief title (optional)",
                }
            ),
            "description": forms.Textarea(
                attrs={
                    "class": "form-control",
                    "rows": 5,
                    "placeholder": "Please describe what you observed in detail...",
                }
            ),
            "description_en": forms.Textarea(
                attrs={
                    "class": "form-control",
                    "rows": 5,
                    "placeholder": "English description...",
                }
            ),
            "location_text": forms.TextInput(
                attrs={
                    "class": "form-control",
                    "placeholder": "e.g., Building A, Floor 2, Room 205",
                }
            ),
            "incident_datetime": forms.DateTimeInput(
                attrs={
                    "class": "form-control",
                    "type": "datetime-local",
                }
            ),
            "patient_file_number": forms.TextInput(
                attrs={
                    "class": "form-control",
                    "placeholder": "Patient MRN / file number",
                }
            ),
            "person_noted": forms.TextInput(
                attrs={
                    "class": "form-control",
                    "placeholder": "Person who was informed about this",
                }
            ),
            "communication_method": forms.TextInput(
                attrs={
                    "class": "form-control",
                    "placeholder": "e.g., extension, mobile, in-person",
                }
            ),
            "communication_datetime": forms.DateTimeInput(
                attrs={
                    "class": "form-control",
                    "type": "datetime-local",
                }
            ),
            "assigned_department": forms.Select(
                attrs={
                    "class": "form-select",
                }
            ),
            "assigned_to": forms.Select(
                attrs={
                    "class": "form-select",
                }
            ),
            "department_noted": forms.Select(
                attrs={
                    "class": "form-select",
                }
            ),
        }

    location = forms.ModelChoiceField(
        label=_("Location"),
        queryset=None,
        empty_label=_("Select Location"),
        required=False,
        widget=forms.Select(attrs={"class": "form-select", "id": "locationSelect", "data-action": "load-sections"}),
    )

    main_section = forms.ModelChoiceField(
        label=_("Section"),
        queryset=None,
        empty_label=_("Select Section"),
        required=False,
        widget=forms.Select(
            attrs={"class": "form-select", "id": "mainSectionSelect", "data-action": "load-subsections"}
        ),
    )

    subsection = forms.ModelChoiceField(
        label=_("Subsection"),
        queryset=None,
        empty_label=_("Select Subsection"),
        required=False,
        widget=forms.Select(attrs={"class": "form-select", "id": "subsectionSelect"}),
    )

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

        from apps.organizations.models import Location, MainSection, SubSection
        from apps.px_sources.models import PXSource

        self.fields["main_section"].queryset = MainSection.objects.none()
        self.fields["subsection"].queryset = SubSection.objects.none()
        self.fields["location"].queryset = Location.active_locations()

        location_id = self.data.get("location") or self.initial.get("location")
        if location_id:
            available_sections = (
                SubSection.objects.filter(location_id=location_id)
                .values_list("main_section_id", flat=True)
                .distinct()
            )
            self.fields["main_section"].queryset = MainSection.objects.filter(
                id__in=available_sections
            ).order_by("name_en")

            section_id = self.data.get("main_section") or self.initial.get("main_section")
            if section_id:
                self.fields["subsection"].queryset = SubSection.objects.filter(
                    location_id=location_id, main_section_id=section_id
                ).order_by("name_en")

        self.fields["category"].queryset = ObservationCategory.objects.filter(is_active=True).order_by(
            "sort_order", "name_en"
        )
        self.fields["category"].empty_label = "Select a category (optional)"

        # Sub-category filtered by selected category
        self.fields["sub_category"].queryset = ObservationSubCategory.objects.none()
        self.fields["sub_category"].empty_label = "Select a sub-category (optional)"
        category_id = self.data.get("category") or self.initial.get("category")
        if category_id:
            self.fields["sub_category"].queryset = ObservationSubCategory.objects.filter(
                category_id=category_id, is_active=True
            ).order_by("sort_order", "name_en")

        # Load active PX sources for optional selection
        self.fields["px_source"].queryset = PXSource.objects.filter(is_active=True).order_by("name_en")
        self.fields["px_source"].empty_label = "Select source (optional)"
        self.fields["px_source"].required = False

        if not self.instance.pk:
            self.initial["incident_datetime"] = timezone.now().strftime("%Y-%m-%dT%H:%M")

        if request:
            user = request.user
            hospital = user.hospital
            if hospital:
                self.fields["assigned_department"].queryset = Department.objects.filter(
                    hospital=hospital, status="active"
                ).order_by("name")
            else:
                self.fields["assigned_department"].queryset = Department.objects.filter(status="active").order_by(
                    "name"
                )
            self.fields["assigned_department"].empty_label = "Select department (optional)"

            if hospital:
                from apps.core.utils import get_assignable_users
                self.fields["assigned_to"].queryset = get_assignable_users(hospital)
            else:
                self.fields["assigned_to"].queryset = User.objects.filter(is_active=True).order_by(
                    "first_name", "last_name"
                )
            self.fields["assigned_to"].empty_label = "Select assignee (optional)"

            # Department noted uses same queryset as assigned_department
            self.fields["department_noted"].queryset = self.fields["assigned_department"].queryset
            self.fields["department_noted"].empty_label = "Select department (optional)"

    def clean_description(self):
        description = self.cleaned_data.get("description", "")
        if len(description.strip()) < 10:
            raise forms.ValidationError("Please provide a more detailed description (at least 10 characters).")
        return description


class ObservationTriageForm(forms.Form):
    """
    Form for triaging observations.

    Used by PX360 staff to assign department, owner, and update status.
    """

    assigned_department = forms.ModelChoiceField(
        queryset=Department.objects.filter(status="active"),
        required=False,
        empty_label="Select department",
        widget=forms.Select(attrs={"class": "form-select"}),
    )

    assigned_to = forms.ModelChoiceField(
        queryset=User.objects.filter(is_active=True),
        required=False,
        empty_label="Select assignee",
        widget=forms.Select(attrs={"class": "form-select"}),
    )

    status = forms.ChoiceField(choices=ObservationStatus.choices, widget=forms.Select(attrs={"class": "form-select"}))

    note = forms.CharField(
        required=False,
        widget=forms.Textarea(
            attrs={
                "class": "form-control",
                "rows": 3,
                "placeholder": "Add a note about this triage action (optional)...",
            }
        ),
    )

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

        # Filter departments by hospital if provided
        if hospital:
            self.fields["assigned_department"].queryset = Department.objects.filter(hospital=hospital, status="active")
            from apps.core.utils import get_assignable_users
            self.fields["assigned_to"].queryset = get_assignable_users(hospital)


class ObservationStatusForm(forms.Form):
    """
    Form for changing observation status.
    """

    status = forms.ChoiceField(choices=ObservationStatus.choices, widget=forms.Select(attrs={"class": "form-select"}))

    comment = forms.CharField(
        required=False,
        widget=forms.Textarea(
            attrs={
                "class": "form-control",
                "rows": 3,
                "placeholder": "Add a comment about this status change (optional)...",
            }
        ),
    )


class ObservationNoteForm(forms.ModelForm):
    """
    Form for adding internal notes to observations.
    """

    class Meta:
        model = ObservationNote
        fields = ["note", "is_internal"]
        widgets = {
            "note": forms.Textarea(
                attrs={
                    "class": "form-control",
                    "rows": 3,
                    "placeholder": "Add your note here...",
                }
            ),
            "is_internal": forms.CheckboxInput(
                attrs={
                    "class": "form-check-input",
                }
            ),
        }


class ObservationCategoryForm(forms.ModelForm):
    """
    Form for managing observation categories.
    """

    class Meta:
        model = ObservationCategory
        fields = ["name_en", "name_ar", "description", "icon", "sort_order", "is_active"]
        widgets = {
            "name_en": forms.TextInput(
                attrs={
                    "class": "form-control",
                    "placeholder": "Category name in English",
                }
            ),
            "name_ar": forms.TextInput(
                attrs={
                    "class": "form-control",
                    "placeholder": "Category name in Arabic",
                    "dir": "rtl",
                }
            ),
            "description": forms.Textarea(
                attrs={
                    "class": "form-control",
                    "rows": 3,
                    "placeholder": "Optional description...",
                }
            ),
            "icon": forms.TextInput(
                attrs={
                    "class": "form-control",
                    "placeholder": "e.g., bi-exclamation-triangle",
                }
            ),
            "sort_order": forms.NumberInput(
                attrs={
                    "class": "form-control",
                    "min": 0,
                }
            ),
            "is_active": forms.CheckboxInput(
                attrs={
                    "class": "form-check-input",
                }
            ),
        }


class ObservationFilterForm(forms.Form):
    """
    Form for filtering observations in the list view.
    """

    search = forms.CharField(
        required=False,
        widget=forms.TextInput(
            attrs={
                "class": "form-control",
                "placeholder": "Search by tracking code, description...",
            }
        ),
    )

    status = forms.ChoiceField(
        required=False,
        choices=[("", "All Statuses")] + list(ObservationStatus.choices),
        widget=forms.Select(attrs={"class": "form-select"}),
    )

    severity = forms.ChoiceField(
        required=False,
        choices=[("", "All Severities")] + list(ObservationSeverity.choices),
        widget=forms.Select(attrs={"class": "form-select"}),
    )

    category = forms.ModelChoiceField(
        required=False,
        queryset=ObservationCategory.objects.filter(is_active=True),
        empty_label="All Categories",
        widget=forms.Select(attrs={"class": "form-select"}),
    )

    assigned_department = forms.ModelChoiceField(
        required=False,
        queryset=Department.objects.filter(status="active"),
        empty_label="All Departments",
        widget=forms.Select(attrs={"class": "form-select"}),
    )

    assigned_to = forms.ModelChoiceField(
        required=False,
        queryset=User.objects.filter(is_active=True),
        empty_label="All Assignees",
        widget=forms.Select(attrs={"class": "form-select"}),
    )

    date_from = forms.DateField(
        required=False,
        widget=forms.DateInput(
            attrs={
                "class": "form-control",
                "type": "date",
            }
        ),
    )

    date_to = forms.DateField(
        required=False,
        widget=forms.DateInput(
            attrs={
                "class": "form-control",
                "type": "date",
            }
        ),
    )

    is_anonymous = forms.ChoiceField(
        required=False,
        choices=[
            ("", "All"),
            ("yes", "Anonymous Only"),
            ("no", "Identified Only"),
        ],
        widget=forms.Select(attrs={"class": "form-select"}),
    )


class ConvertToActionForm(forms.Form):
    """
    Form for converting an observation to a PX Action.
    """

    title = forms.CharField(
        max_length=500,
        widget=forms.TextInput(
            attrs={
                "class": "form-control",
            }
        ),
    )

    description = forms.CharField(
        widget=forms.Textarea(
            attrs={
                "class": "form-control",
                "rows": 4,
            }
        )
    )

    category = forms.ChoiceField(
        choices=[
            ("clinical_quality", "Clinical Quality"),
            ("patient_safety", "Patient Safety"),
            ("service_quality", "Service Quality"),
            ("staff_behavior", "Staff Behavior"),
            ("facility", "Facility & Environment"),
            ("process_improvement", "Process Improvement"),
            ("other", "Other"),
        ],
        widget=forms.Select(attrs={"class": "form-select"}),
    )

    priority = forms.ChoiceField(
        choices=[
            ("low", "Low"),
            ("medium", "Medium"),
            ("high", "High"),
            ("critical", "Critical"),
        ],
        widget=forms.Select(attrs={"class": "form-select"}),
    )

    assigned_department = forms.ModelChoiceField(
        required=False,
        queryset=Department.objects.filter(status="active"),
        empty_label="Select department",
        widget=forms.Select(attrs={"class": "form-select"}),
    )

    assigned_to = forms.ModelChoiceField(
        required=False,
        queryset=User.objects.filter(is_active=True),
        empty_label="Select assignee",
        widget=forms.Select(attrs={"class": "form-select"}),
    )

    def __init__(self, *args, hospital=None, **kwargs):
        super().__init__(*args, **kwargs)
        if hospital:
            from apps.core.utils import get_assignable_users
            self.fields["assigned_to"].queryset = get_assignable_users(hospital)
            self.fields["assigned_department"].queryset = Department.objects.filter(hospital=hospital, status="active")


class ObservationSendToDepartmentForm(forms.Form):
    """
    Form for sending an observation to a department for response.
    """

    department = forms.ModelChoiceField(
        queryset=Department.objects.filter(status="active"),
        required=True,
        empty_label="Select department",
        widget=forms.Select(attrs={"class": "form-select"}),
    )

    note_en = forms.CharField(
        required=False,
        widget=forms.Textarea(
            attrs={
                "class": "form-control",
                "rows": 3,
                "placeholder": "Optional note in English...",
            }
        ),
    )

    note_ar = forms.CharField(
        required=False,
        widget=forms.Textarea(
            attrs={
                "class": "form-control",
                "rows": 3,
                "placeholder": "ملاحظة اختيارية بالعربية...",
                "dir": "rtl",
            }
        ),
    )

    def __init__(self, *args, hospital=None, **kwargs):
        super().__init__(*args, **kwargs)
        if hospital:
            self.fields["department"].queryset = Department.objects.filter(hospital=hospital, status="active")


class ObservationDepartmentResponseForm(forms.Form):
    """
    Form for submitting a department response to an observation.
    """

    response_en = forms.CharField(
        required=False,
        widget=forms.Textarea(
            attrs={
                "class": "form-control",
                "rows": 6,
                "placeholder": "Enter your response in English...",
            }
        ),
    )

    response_ar = forms.CharField(
        required=False,
        widget=forms.Textarea(
            attrs={
                "class": "form-control",
                "rows": 6,
                "placeholder": "أدخل ردك باللغة العربية...",
                "dir": "rtl",
            }
        ),
    )

    def clean(self):
        cleaned_data = super().clean()
        response_en = cleaned_data.get("response_en", "").strip()
        response_ar = cleaned_data.get("response_ar", "").strip()

        if not response_en and not response_ar:
            raise forms.ValidationError("Please enter a response in at least one language.")

        return cleaned_data


class ObservationTrackForm(forms.Form):
    """
    Form for tracking an observation by its tracking code.
    """

    tracking_code = forms.CharField(
        max_length=20,
        widget=forms.TextInput(
            attrs={
                "class": "form-control form-control-lg",
                "placeholder": "Enter your tracking code (e.g., OBS-ABC123)",
                "autofocus": True,
            }
        ),
    )

    def clean_tracking_code(self):
        """Normalize tracking code."""
        code = self.cleaned_data.get("tracking_code", "").strip().upper()
        if not code:
            raise forms.ValidationError("Please enter a tracking code.")
        return code


class PublicObservationForm(forms.ModelForm):
    reporter_name = forms.CharField(
        label=_("Reporter Name"),
        max_length=200,
        required=True,
        widget=forms.TextInput(attrs={"class": "form-control", "placeholder": _("Your full name")}),
    )
    reporter_phone = forms.CharField(
        label=_("Mobile Number"),
        max_length=20,
        required=True,
        widget=forms.TextInput(attrs={"class": "form-control", "placeholder": _("Your mobile number")}),
    )
    reporter_email = forms.EmailField(
        label=_("Email Address"),
        required=False,
        widget=forms.EmailInput(attrs={"class": "form-control", "placeholder": _("your@email.com")}),
    )
    hospital = forms.ModelChoiceField(
        label=_("Hospital"),
        queryset=None,
        empty_label=_("Select Hospital"),
        required=True,
        widget=forms.Select(attrs={"class": "form-control", "id": "hospital_select"}),
    )
    category = forms.ModelChoiceField(
        label=_("Category"),
        queryset=None,
        empty_label=_("Select Category"),
        required=False,
        widget=forms.Select(attrs={"class": "form-control"}),
    )
    location = forms.ModelChoiceField(
        label=_("Location"),
        queryset=None,
        empty_label=_("Select Location"),
        required=False,
        widget=forms.Select(attrs={"class": "form-control", "id": "location_select", "data-action": "load-sections"}),
    )
    main_section = forms.ModelChoiceField(
        label=_("Section"),
        queryset=None,
        empty_label=_("Select Section"),
        required=False,
        widget=forms.Select(attrs={"class": "form-control", "id": "main_section_select", "data-action": "load-subsections"}),
    )
    subsection = forms.ModelChoiceField(
        label=_("Subsection"),
        queryset=None,
        empty_label=_("Select Subsection"),
        required=False,
        widget=forms.Select(attrs={"class": "form-control", "id": "subsection_select"}),
    )
    title = forms.CharField(
        label=_("Title"),
        max_length=200,
        required=False,
        widget=forms.TextInput(attrs={"class": "form-control", "placeholder": _("Brief title (optional)")}),
    )
    description = forms.CharField(
        label=_("Description"),
        required=True,
        widget=forms.Textarea(attrs={"class": "form-control", "rows": 5, "placeholder": _("Describe the observation in detail...")}),
    )

    class Meta:
        model = Observation
        fields = [
            "reporter_name",
            "reporter_phone",
            "reporter_email",
            "hospital",
            "category",
            "location",
            "main_section",
            "subsection",
            "title",
            "description",
            "description_en",
        ]

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        from apps.organizations.models import Hospital, Location, MainSection, SubSection

        self.fields["hospital"].queryset = Hospital.objects.filter(status="active").order_by("name")
        self.fields["category"].queryset = ObservationCategory.objects.filter(is_active=True).order_by("name_en")
        self.fields["location"].queryset = Location.active_locations()
        self.fields["main_section"].queryset = MainSection.objects.none()
        self.fields["subsection"].queryset = SubSection.objects.none()

        location_id = None
        if "location" in self.initial:
            location_id = self.initial["location"]
        elif "location" in self.data:
            location_id = self.data["location"]

        if location_id:
            available_sections = (
                SubSection.objects.filter(location_id=location_id).values_list("main_section_id", flat=True).distinct()
            )
            self.fields["main_section"].queryset = MainSection.objects.filter(id__in=available_sections).order_by("name_en")

            section_id = None
            if "main_section" in self.initial:
                section_id = self.initial["main_section"]
            elif "main_section" in self.data:
                section_id = self.data["main_section"]

            if section_id:
                self.fields["subsection"].queryset = SubSection.objects.filter(
                    location_id=location_id, main_section_id=section_id
                ).order_by("name_en")
