"""
Complaints views and viewsets
"""

import logging

from django.db.models import Q
from django.shortcuts import get_object_or_404, render, redirect
from django.urls import reverse
from django.utils import timezone
from rest_framework import status, viewsets
from rest_framework.decorators import action
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response

from apps.core.services import AuditService

from .models import (
    Complaint,
    ComplaintAttachment,
    ComplaintExplanation,
    ComplaintMeeting,
    ComplaintPRInteraction,
    ComplaintStatus,
    ComplaintUpdate,
    InvestigationStatus,
    Inquiry,
)
from .serializers import (
    ComplaintAttachmentSerializer,
    ComplaintListSerializer,
    ComplaintMeetingSerializer,
    ComplaintPRInteractionSerializer,
    ComplaintSerializer,
    ComplaintUpdateSerializer,
    InquirySerializer,
)
from .services.complaint_service import ComplaintService, ComplaintServiceError


logger = logging.getLogger(__name__)


def map_complaint_category_to_action_category(complaint_category_code):
    """
    Map complaint category code to PX Action category.

    Provides intelligent mapping from complaint categories to PX Action categories.
    Returns 'other' as fallback if no match found.
    """
    if not complaint_category_code:
        return "other"

    mapping = {
        # Clinical issues
        "clinical": "clinical_quality",
        "medical": "clinical_quality",
        "diagnosis": "clinical_quality",
        "treatment": "clinical_quality",
        "medication": "clinical_quality",
        "care": "clinical_quality",
        # Safety issues
        "safety": "patient_safety",
        "risk": "patient_safety",
        "incident": "patient_safety",
        "infection": "patient_safety",
        "harm": "patient_safety",
        # Service quality
        "service": "service_quality",
        "communication": "service_quality",
        "wait": "service_quality",
        "response": "service_quality",
        "customer_service": "service_quality",
        "timeliness": "service_quality",
        "waiting_time": "service_quality",
        # Staff behavior
        "staff": "staff_behavior",
        "behavior": "staff_behavior",
        "attitude": "staff_behavior",
        "professionalism": "staff_behavior",
        "rude": "staff_behavior",
        "respect": "staff_behavior",
        # Facility
        "facility": "facility",
        "environment": "facility",
        "cleanliness": "facility",
        "equipment": "facility",
        "infrastructure": "facility",
        "parking": "facility",
        "accessibility": "facility",
        # Process
        "process": "process_improvement",
        "administrative": "process_improvement",
        "billing": "process_improvement",
        "procedure": "process_improvement",
        "workflow": "process_improvement",
        "registration": "process_improvement",
        "appointment": "process_improvement",
    }

    # Try exact match first
    category_lower = complaint_category_code.lower()
    if category_lower in mapping:
        return mapping[category_lower]

    # Try partial match (contains the keyword)
    for keyword, action_category in mapping.items():
        if keyword in category_lower:
            return action_category

    # Fallback to 'other'
    return "other"


class ComplaintViewSet(viewsets.ModelViewSet):
    """
    ViewSet for Complaints with workflow actions.

    Permissions:
    - All authenticated users can view complaints
    - PX Admins and Hospital Admins can create/manage complaints
    """

    queryset = Complaint.objects.all()
    permission_classes = [IsAuthenticated]
    filterset_fields = [
        "status",
        "severity",
        "priority",
        "category",
        "source",
        "hospital",
        "department",
        "staff",
        "assigned_to",
        "is_overdue",
        "hospital__organization",
    ]
    search_fields = [
        "title",
        "description",
        "reference_number",
        "patient__mrn",
        "patient__first_name",
        "patient__last_name",
    ]
    ordering_fields = ["created_at", "due_at", "severity"]
    ordering = ["-created_at"]

    def get_serializer_class(self):
        """Use simplified serializer for list view"""
        if self.action == "list":
            return ComplaintListSerializer
        return ComplaintSerializer

    def get_queryset(self):
        """Filter complaints based on user role"""
        queryset = (
            super()
            .get_queryset()
            .select_related(
                "patient", "hospital", "department", "staff", "assigned_to", "resolved_by", "closed_by", "created_by"
            )
            .prefetch_related("attachments", "updates")
        )

        user = self.request.user

        if user.is_px_admin():
            if hasattr(self.request, "tenant_hospital") and self.request.tenant_hospital:
                return queryset.filter(hospital=self.request.tenant_hospital)
            return queryset

        # Source Users see ONLY complaints THEY created
        if hasattr(user, "source_user_profile") and user.source_user_profile.exists():
            return queryset.filter(created_by=user)

        # Patients see ONLY their own complaints (if they have user accounts)
        # This assumes patients can have user accounts linked via patient.user
        if hasattr(user, "patient_profile"):
            return queryset.filter(patient__user=user)

        # Hospital Admins see complaints for their hospital
        if user.is_hospital_admin() and user.hospital:
            return queryset.filter(hospital=user.hospital)

        # Department Managers see complaints for their department
        if user.is_department_manager() and user.department:
            return queryset.filter(department=user.department)

        # Others see complaints for their hospital
        if user.hospital:
            return queryset.filter(hospital=user.hospital)

        return queryset.none()

    def get_object(self):
        """
        Override get_object to allow PX Admins to access complaints
        for specific actions (request_explanation, resend_explanation, send_notification, assignable_admins).
        """
        queryset = self.filter_queryset(self.get_queryset())

        # PX Admins can access any complaint for specific actions
        if self.request.user.is_px_admin() and self.action in [
            "request_explanation",
            "resend_explanation",
            "send_notification",
            "assignable_admins",
            "escalate_explanation",
            "review_explanation",
        ]:
            # Bypass queryset filtering and get directly by pk
            lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
            lookup_value = self.kwargs[lookup_url_kwarg]
            return get_object_or_404(Complaint, pk=lookup_value)

        # Normal behavior for other users/actions
        lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
        filter_kwargs = {self.lookup_field: self.kwargs[lookup_url_kwarg]}
        obj = get_object_or_404(queryset, **filter_kwargs)

        # May raise a permission denied
        self.check_object_permissions(self.request, obj)
        return obj

    def perform_create(self, serializer):
        """Log complaint creation and trigger AI analysis"""
        complaint = serializer.save(created_by=self.request.user)
        ComplaintService.post_create_hooks(complaint, self.request.user, request=self.request)

    @action(detail=True, methods=["post"])
    def activate(self, request, pk=None):
        """Activate complaint by assigning it to current user."""
        complaint = self.get_object()

        try:
            result = ComplaintService.activate(complaint, request.user, request=request)
        except ComplaintServiceError as e:
            return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)

        return Response(
            {
                "message": "Complaint activated successfully",
                "assigned_to": {
                    "id": str(request.user.id),
                    "name": request.user.get_full_name(),
                    "roles": request.user.get_role_names(),
                },
                "assigned_at": complaint.assigned_at.isoformat(),
                "status": complaint.status,
            }
        )

    @action(detail=True, methods=["post"])
    def assign(self, request, pk=None):
        """Assign complaint to user (PX Admin or Hospital Admin)"""
        complaint = self.get_object()
        user_id = request.data.get("user_id")

        if not user_id:
            return Response({"error": "user_id is required"}, status=status.HTTP_400_BAD_REQUEST)

        from apps.accounts.models import User

        try:
            target_user = User.objects.get(id=user_id)
            ComplaintService.assign(complaint, target_user, request.user, request=request)
        except User.DoesNotExist:
            return Response({"error": "User not found"}, status=status.HTTP_404_NOT_FOUND)
        except ComplaintServiceError as e:
            return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)

        return Response({"message": "Complaint assigned successfully"})

    @action(detail=True, methods=["get"])
    def assignable_admins(self, request, pk=None):
        """
        Get assignable admins (PX Admins and Hospital Admins) for this complaint.

        Returns list of all PX Admins and Hospital Admins.
        Supports searching by name.
        """
        complaint = self.get_object()

        # Check if user has permission to assign admins
        if not request.user.is_px_admin():
            return Response(
                {"error": "Only PX Admins can assign complaints to admins"}, status=status.HTTP_403_FORBIDDEN
            )

        from apps.accounts.models import User

        # Get search parameter
        search = request.query_params.get("search", "").strip()

        # Simple query - get all PX Admins and Hospital Admins
        base_query = Q(groups__name="PX Admin") | Q(groups__name="Hospital Admin")

        queryset = (
            User.objects.filter(base_query, is_active=True)
            .select_related("hospital")
            .prefetch_related("groups")
            .order_by("first_name", "last_name")
        )

        # Search by name or email if provided
        if search:
            queryset = queryset.filter(
                Q(first_name__icontains=search) | Q(last_name__icontains=search) | Q(email__icontains=search)
            )

        # Serialize
        admins_list = []
        for user in queryset:
            roles = user.get_role_names()
            role_display = ", ".join(roles)

            admins_list.append(
                {
                    "id": str(user.id),
                    "name": user.get_full_name(),
                    "email": user.email,
                    "roles": roles,
                    "role_display": role_display,
                    "hospital": user.hospital.name if user.hospital else None,
                    "is_px_admin": user.is_px_admin(),
                    "is_hospital_admin": user.is_hospital_admin(),
                }
            )

        return Response(
            {
                "complaint_id": str(complaint.id),
                "hospital_id": str(complaint.hospital.id),
                "hospital_name": complaint.hospital.name,
                "current_assignee": {
                    "id": str(complaint.assigned_to.id),
                    "name": complaint.assigned_to.get_full_name(),
                    "email": complaint.assigned_to.email,
                    "roles": complaint.assigned_to.get_role_names(),
                }
                if complaint.assigned_to
                else None,
                "admin_count": len(admins_list),
                "admins": admins_list,
            }
        )

    @action(detail=True, methods=["post"])
    def change_status(self, request, pk=None):
        """Change complaint status"""
        complaint = self.get_object()

        try:
            ComplaintService.change_status(
                complaint,
                request.data.get("status", ""),
                request.user,
                request=request,
                note=request.data.get("note", ""),
                resolution=request.data.get("resolution", ""),
                resolution_category=request.data.get("resolution_category", ""),
            )
        except ComplaintServiceError as e:
            return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)

        return Response({"message": "Status updated successfully"})

    @action(detail=True, methods=["post"])
    def add_note(self, request, pk=None):
        """Add note to complaint"""
        complaint = self.get_object()
        note = request.data.get("note")

        try:
            update = ComplaintService.add_note(complaint, note, request.user, request=request)
        except ComplaintServiceError as e:
            return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)

        serializer = ComplaintUpdateSerializer(update)
        return Response(serializer.data, status=status.HTTP_201_CREATED)

    @action(detail=True, methods=["get"])
    def staff_suggestions(self, request, pk=None):
        """
        Get staff matching suggestions for a complaint.

        Returns potential staff matches from AI analysis,
        allowing PX Admins to review and select correct staff.
        """
        complaint = self.get_object()

        # Check if user is PX Admin
        if not request.user.is_px_admin():
            return Response({"error": "Only PX Admins can access staff suggestions"}, status=status.HTTP_403_FORBIDDEN)

        # Get AI analysis metadata
        ai_analysis = complaint.metadata.get("ai_analysis", {})
        staff_matches = ai_analysis.get("staff_matches", [])
        extracted_name = ai_analysis.get("extracted_staff_name", "")
        needs_review = ai_analysis.get("needs_staff_review", False)
        matched_staff_id = ai_analysis.get("matched_staff_id")

        return Response(
            {
                "extracted_name": extracted_name,
                "staff_matches": staff_matches,
                "current_staff_id": matched_staff_id,
                "needs_staff_review": needs_staff_review,
                "staff_match_count": len(staff_matches),
            }
        )

    @action(detail=True, methods=["get"])
    def hospital_staff(self, request, pk=None):
        """
        Get all staff from complaint's hospital for manual selection.

        Allows PX Admins to manually select staff.
        Supports filtering by department.
        """
        complaint = self.get_object()

        # Check if user is PX Admin
        if not request.user.is_px_admin():
            return Response(
                {"error": "Only PX Admins can access hospital staff list"}, status=status.HTTP_403_FORBIDDEN
            )

        from apps.organizations.models import Staff

        # Get query params
        department_id = request.query_params.get("department_id")
        search = request.query_params.get("search", "").strip()

        # Build query
        queryset = Staff.objects.filter(hospital=complaint.hospital, status="active").select_related("department")

        # Filter by department if specified
        if department_id:
            queryset = queryset.filter(department_id=department_id)

        # Search by name if provided
        if search:
            queryset = queryset.filter(
                Q(first_name__icontains=search)
                | Q(last_name__icontains=search)
                | Q(first_name_ar__icontains=search)
                | Q(last_name_ar__icontains=search)
                | Q(job_title__icontains=search)
            )

        # Order by department and name
        queryset = queryset.order_by("department__name", "first_name", "last_name")

        # Serialize
        staff_list = []
        for staff in queryset:
            staff_list.append(
                {
                    "id": str(staff.id),
                    "name_en": f"{staff.first_name} {staff.last_name}",
                    "name_ar": f"{staff.first_name_ar} {staff.last_name_ar}"
                    if staff.first_name_ar and staff.last_name_ar
                    else "",
                    "job_title": staff.job_title,
                    "specialization": staff.specialization,
                    "department": staff.department.name if staff.department else None,
                    "department_id": str(staff.department.id) if staff.department else None,
                }
            )

        return Response(
            {
                "hospital_id": str(complaint.hospital.id),
                "hospital_name": complaint.hospital.name,
                "staff_count": len(staff_list),
                "staff": staff_list,
            }
        )

    @action(detail=True, methods=["post"])
    def assign_staff(self, request, pk=None):
        """
        Manually assign staff to a complaint.

        Allows PX Admins to assign specific staff member,
        especially when AI matching is ambiguous.
        """
        complaint = self.get_object()

        # Check if complaint is in active status
        if not complaint.is_active_status:
            return Response(
                {
                    "error": f"Cannot assign staff to complaint with status '{complaint.get_status_display()}'. Complaint must be Open, In Progress, or Partially Resolved."
                },
                status=status.HTTP_400_BAD_REQUEST,
            )

        # Check if user is PX Admin
        if not request.user.is_px_admin():
            return Response(
                {"error": "Only PX Admins can assign staff to complaints"}, status=status.HTTP_403_FORBIDDEN
            )

        staff_id = request.data.get("staff_id")
        reason = request.data.get("reason", "")

        if not staff_id:
            return Response({"error": "staff_id is required"}, status=status.HTTP_400_BAD_REQUEST)

        from apps.organizations.models import Staff

        try:
            staff = Staff.objects.get(id=staff_id)
        except Staff.DoesNotExist:
            return Response({"error": "Staff not found"}, status=status.HTTP_404_NOT_FOUND)

        # Check staff belongs to same hospital
        if staff.hospital != complaint.hospital:
            return Response(
                {"error": "Staff does not belong to complaint hospital"}, status=status.HTTP_400_BAD_REQUEST
            )

        # Update complaint
        old_staff_id = str(complaint.staff.id) if complaint.staff else None
        complaint.staff = staff
        # Auto-set department from staff
        complaint.department = staff.department
        complaint.save(update_fields=["staff", "department"])

        # Update metadata to clear review flag
        if not complaint.metadata:
            complaint.metadata = {}
        if "ai_analysis" in complaint.metadata:
            complaint.metadata["ai_analysis"]["needs_staff_review"] = False
            complaint.metadata["ai_analysis"]["staff_manually_assigned"] = True
            complaint.metadata["ai_analysis"]["staff_assigned_by"] = str(request.user.id)
            complaint.metadata["ai_analysis"]["staff_assigned_at"] = timezone.now().isoformat()
            complaint.metadata["ai_analysis"]["staff_assignment_reason"] = reason
        complaint.save(update_fields=["metadata"])

        # Create update
        ComplaintUpdate.objects.create(
            complaint=complaint,
            update_type="assignment",
            message=f"Staff assigned to {staff.first_name} {staff.last_name} ({staff.job_title}). {reason}"
            if reason
            else f"Staff assigned to {staff.first_name} {staff.last_name} ({staff.job_title})",
            created_by=request.user,
            metadata={"old_staff_id": old_staff_id, "new_staff_id": str(staff.id), "manual_assignment": True},
        )

        # Log audit
        AuditService.log_from_request(
            event_type="staff_assigned",
            description=f"Staff {staff.first_name} {staff.last_name} manually assigned to complaint by {request.user.get_full_name()}",
            request=request,
            content_object=complaint,
            metadata={"old_staff_id": old_staff_id, "new_staff_id": str(staff.id), "reason": reason},
        )

        return Response(
            {
                "message": "Staff assigned successfully",
                "staff_id": str(staff.id),
                "staff_name": f"{staff.first_name} {staff.last_name}",
            }
        )

    @action(detail=True, methods=["post"])
    def change_department(self, request, pk=None):
        """Change complaint department"""
        complaint = self.get_object()
        department_id = request.data.get("department_id")

        if not department_id:
            return Response({"error": "department_id is required"}, status=status.HTTP_400_BAD_REQUEST)

        from apps.organizations.models import Department

        try:
            department = Department.objects.get(id=department_id)
            ComplaintService.change_department(complaint, department, request.user, request=request)
        except Department.DoesNotExist:
            return Response({"error": "Department not found"}, status=status.HTTP_404_NOT_FOUND)
        except ComplaintServiceError as e:
            return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)

        return Response(
            {
                "message": "Department changed successfully",
                "department_id": str(department.id),
                "department_name": department.name,
            }
        )

    @action(detail=True, methods=["post"])
    def create_action_from_ai(self, request, pk=None):
        """Create PX Action using AI service to generate action details from complaint"""
        complaint = self.get_object()

        # Use AI service to generate action data
        from apps.core.ai_service import AIService

        try:
            action_data = AIService.create_px_action_from_complaint(complaint)
        except Exception as e:
            return Response(
                {"error": f"Failed to generate action data: {str(e)}"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )

        # Get optional assigned_to from request (AI doesn't assign by default)
        assigned_to_id = request.data.get("assigned_to")
        assigned_to = None
        if assigned_to_id:
            from apps.accounts.models import User

            try:
                assigned_to = User.objects.get(id=assigned_to_id)
            except User.DoesNotExist:
                return Response({"error": "Assigned user not found"}, status=status.HTTP_404_NOT_FOUND)

        # Create PX Action
        from apps.px_action_center.models import PXAction, PXActionLog
        from django.contrib.contenttypes.models import ContentType

        complaint_content_type = ContentType.objects.get_for_model(Complaint)

        action = PXAction.objects.create(
            source_type="complaint",
            content_type=complaint_content_type,
            object_id=complaint.id,
            title=action_data["title"],
            description=action_data["description"],
            hospital=complaint.hospital,
            department=complaint.department,
            category=action_data["category"],
            priority=action_data["priority"],
            severity=action_data["severity"],
            assigned_to=assigned_to,
            status="open",
            metadata={
                "source_complaint_id": str(complaint.id),
                "source_complaint_title": complaint.title,
                "ai_generated": True,
                "ai_reasoning": action_data.get("reasoning", ""),
                "created_from_ai_suggestion": True,
            },
        )

        # Create action log entry
        PXActionLog.objects.create(
            action=action,
            log_type="note",
            message=f"Action generated by AI for complaint: {complaint.title}",
            created_by=request.user,
            metadata={
                "complaint_id": str(complaint.id),
                "ai_generated": True,
                "category": action_data["category"],
                "priority": action_data["priority"],
                "severity": action_data["severity"],
            },
        )

        # Create complaint update
        ComplaintUpdate.objects.create(
            complaint=complaint,
            update_type="note",
            message=f"PX Action created from AI-generated suggestion (Action #{action.id}) - {action_data['category']}",
            created_by=request.user,
            metadata={"action_id": str(action.id), "category": action_data["category"]},
        )

        # Log audit
        AuditService.log_from_request(
            event_type="action_created_from_ai",
            description=f"PX Action created from AI analysis for complaint: {complaint.title}",
            request=request,
            content_object=action,
            metadata={
                "complaint_id": str(complaint.id),
                "category": action_data["category"],
                "priority": action_data["priority"],
                "severity": action_data["severity"],
                "ai_reasoning": action_data.get("reasoning", ""),
            },
        )

        return Response(
            {
                "action_id": str(action.id),
                "message": "Action created successfully from AI analysis",
                "action_data": {
                    "title": action_data["title"],
                    "category": action_data["category"],
                    "priority": action_data["priority"],
                    "severity": action_data["severity"],
                },
            },
            status=status.HTTP_201_CREATED,
        )

    @action(detail=True, methods=["post"])
    def send_notification(self, request, pk=None):
        """
        Send email notification to staff member or department head.

        Sends complaint notification with AI-generated summary (editable by user).
        Logs the operation to NotificationLog and ComplaintUpdate.

        Recipient Priority:
        1. Staff with user account
        2. Staff with email field
        3. Department manager
        """
        complaint = self.get_object()

        # Get email message (required)
        email_message = request.data.get("email_message", "").strip()
        if not email_message:
            return Response({"error": "email_message is required"}, status=status.HTTP_400_BAD_REQUEST)

        # Get additional message (optional)
        additional_message = request.data.get("additional_message", "").strip()

        # Determine recipient with priority logic
        recipient = None
        recipient_display = None
        recipient_type = None
        recipient_email = None

        # Priority 1: Staff member with user account
        if complaint.staff and complaint.staff.user:
            recipient = complaint.staff.user
            recipient_display = str(complaint.staff)
            recipient_type = "Staff Member (User Account)"
            recipient_email = recipient.email

        # Priority 2: Staff member with email field (no user account)
        elif complaint.staff and complaint.staff.email:
            recipient_display = str(complaint.staff)
            recipient_type = "Staff Member (Email)"
            recipient_email = complaint.staff.email

        # Priority 3: Department head
        elif complaint.department and complaint.department.manager:
            recipient = complaint.department.manager
            recipient_display = recipient.get_full_name()
            recipient_type = "Department Head"
            recipient_email = recipient.email

        # Check if we found a recipient with email
        if not recipient_email:
            return Response(
                {
                    "error": "No valid recipient found. Complaint must have staff with email, or a department manager with email."
                },
                status=status.HTTP_400_BAD_REQUEST,
            )

        # Construct email content
        subject = f"Complaint Notification - #{complaint.id}"

        # Build email body
        email_body = f"""
Dear {recipient_display},

You have been assigned to review the following complaint:

COMPLAINT DETAILS:
----------------
ID: #{complaint.id}
Title: {complaint.title}
Severity: {complaint.get_severity_display()}
Priority: {complaint.get_priority_display()}
Status: {complaint.get_status_display()}

SUMMARY:
--------
{email_message}

"""

        # Add patient info if available
        if complaint.patient:
            email_body += f"""
PATIENT INFORMATION:
------------------
Name: {complaint.patient.get_full_name()}
MRN: {complaint.patient.mrn}
"""

        # Add additional message if provided
        if additional_message:
            email_body += f"""

ADDITIONAL MESSAGE:
------------------
{additional_message}
"""

        # Add link to complaint
        from django.contrib.sites.shortcuts import get_current_site

        site = get_current_site(request)
        complaint_url = f"https://{site.domain}/complaints/{complaint.id}/"

        email_body += f"""

To view the full complaint details, please visit:
{complaint_url}

Thank you for your attention to this matter.

---
This is an automated message from PX360 Complaint Management System.
"""

        # Send email using NotificationService
        from apps.notifications.services import NotificationService, get_email_header_html

        try:
            notification_log = NotificationService.send_email(
                email=recipient_email,
                subject=subject,
                message=email_body,
                html_message=f"""
<div style="font-family: 'Segoe UI', Tahoma, sans-serif; max-width: 600px; margin: 0 auto; border: 1px solid #e5e7eb; border-radius: 8px; overflow: hidden;">
    {get_email_header_html()}
    <div style="padding: 20px;">
        <h2 style="color: #005696; font-size: 18px; margin: 0 0 12px 0;">{subject}</h2>
        <p style="margin: 0 0 12px 0;">Dear {recipient_display},</p>
        <p style="margin: 0 0 12px 0;">You have been assigned to review the following complaint:</p>
        <table style="width: 100%; border-collapse: collapse; margin: 0 0 12px 0;">
            <tr><td style="padding: 4px 0; color: #6b7280; width: 120px;">Reference:</td><td style="padding: 4px 0;"><strong>#{complaint.id}</strong></td></tr>
            <tr><td style="padding: 4px 0; color: #6b7280;">Title:</td><td style="padding: 4px 0;">{complaint.title}</td></tr>
            <tr><td style="padding: 4px 0; color: #6b7280;">Severity:</td><td style="padding: 4px 0;">{complaint.get_severity_display()}</td></tr>
            <tr><td style="padding: 4px 0; color: #6b7280;">Priority:</td><td style="padding: 4px 0;">{complaint.get_priority_display()}</td></tr>
        </table>
        <div style="text-align: center; margin: 20px 0;">
            <a href="{complaint_url}" style="background: #005696; color: white; padding: 10px 24px; border-radius: 8px; text-decoration: none; font-weight: 600;">View Complaint</a>
        </div>
    </div>
</div>
""",
                related_object=complaint,
                metadata={
                    "notification_type": "complaint_notification",
                    "recipient_type": recipient_type,
                    "recipient_id": str(recipient.id) if recipient else None,
                    "sender_id": str(request.user.id),
                    "has_additional_message": bool(additional_message),
                },
            )
        except Exception as e:
            return Response({"error": f"Failed to send email: {str(e)}"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

        # Create ComplaintUpdate entry
        ComplaintUpdate.objects.create(
            complaint=complaint,
            update_type="communication",
            message=f"Email notification sent to {recipient_type}: {recipient_display}",
            created_by=request.user,
            metadata={
                "recipient_type": recipient_type,
                "recipient_id": str(recipient.id) if recipient else None,
                "notification_log_id": str(notification_log.id) if notification_log else None,
            },
        )

        # Log audit
        AuditService.log_from_request(
            event_type="notification_sent",
            description=f"Email notification sent to {recipient_type}: {recipient_display}",
            request=request,
            content_object=complaint,
            metadata={
                "recipient_type": recipient_type,
                "recipient_id": str(recipient.id) if recipient else None,
                "recipient_email": recipient_email,
            },
        )

        return Response(
            {
                "success": True,
                "message": "Email notification sent successfully",
                "recipient": recipient_display,
                "recipient_type": recipient_type,
                "recipient_email": recipient_email,
            }
        )

    @action(detail=True, methods=["post"])
    def send_to_department(self, request, pk=None):
        """
        Send complaint to department for response.
        Delegates to ComplaintService for shared logic.
        Routes through department champion.
        """
        complaint = self.get_object()

        if not complaint.is_active_status:
            return Response(
                {"error": f"Cannot send complaint to department with status '{complaint.get_status_display()}'"},
                status=status.HTTP_400_BAD_REQUEST,
            )

        involved_staff = complaint.involved_staff.select_related(
            "staff", "staff__department", "staff__department__champion", "staff__department__manager"
        ).all()

        if not involved_staff.exists():
            return Response(
                {"error": "No involved staff found for this complaint"},
                status=status.HTTP_400_BAD_REQUEST,
            )

        department_groups = {}
        for staff_inv in involved_staff:
            staff = staff_inv.staff
            dept = staff.department
            if dept and dept.champion:
                dept_key = str(dept.id)
                if dept_key not in department_groups:
                    champion = dept.champion
                    champion_email = champion.email or (champion.user.email if hasattr(champion, 'user') and champion.user else None)
                    dept_manager = dept.manager
                    department_groups[dept_key] = {
                        "department_id": dept_key,
                        "department_name": dept.get_localized_name(),
                        "champion": champion,
                        "champion_id": str(champion.id),
                        "champion_name": champion.get_full_name(),
                        "champion_email": champion_email,
                        "dept_manager": dept_manager,
                        "dept_manager_id": str(dept_manager.id) if dept_manager else None,
                        "dept_manager_name": dept_manager.get_full_name() if dept_manager else None,
                        "dept_manager_email": dept_manager.email if dept_manager else None,
                        "staff_list": [],
                    }
                department_groups[dept_key]["staff_list"].append({
                    "staff_name": staff.get_full_name(),
                    "role": staff_inv.get_role_display(),
                })

        if not department_groups:
            return Response(
                {"error": "No departments with assigned champions found for involved staff"},
                status=status.HTTP_400_BAD_REQUEST,
            )

        request_message = request.data.get("request_message", "").strip()

        from django.contrib.sites.shortcuts import get_current_site

        site = get_current_site(request)
        domain = site.domain

        selected_dept_ids = list(department_groups.keys())

        try:
            result = ComplaintService.send_to_department(
                complaint,
                department_groups,
                selected_dept_ids,
                request_message,
                request.user,
                domain,
                request=request,
            )
        except ComplaintServiceError as e:
            return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)

        return Response(
            {
                "success": result["champion_count"] > 0,
                "message": "Explanation requests sent to department champions",
                "results": result["results"],
                "champion_count": result["champion_count"],
                "manager_notified": result["manager_count"] > 0,
            }
        )

    @action(detail=True, methods=["post"])
    def resend_explanation(self, request, pk=None):
        """
        Resend explanation request email to staff member only.

        Regenerates the token with a new value and resends the email to the staff member.
        Manager is not resent the informational email - they already received it initially.
        Only allows resending if explanation has not been submitted yet.
        """
        complaint = self.get_object()

        # Check if complaint is in active status
        if not complaint.is_active_status:
            return Response(
                {
                    "error": f"Cannot resend explanation for complaint with status '{complaint.get_status_display()}'. Complaint must be Open, In Progress, or Partially Resolved."
                },
                status=status.HTTP_400_BAD_REQUEST,
            )

        # Check if complaint has staff assigned
        if not complaint.staff:
            return Response({"error": "No staff assigned to this complaint"}, status=status.HTTP_400_BAD_REQUEST)

        # Check if explanation exists for this staff
        from .models import ComplaintExplanation

        try:
            explanation = ComplaintExplanation.objects.filter(complaint=complaint, staff=complaint.staff).latest(
                "created_at"
            )
        except ComplaintExplanation.DoesNotExist:
            return Response(
                {"error": "No explanation found for this complaint and staff"}, status=status.HTTP_404_NOT_FOUND
            )

        # Check if already submitted (can only resend if not submitted)
        if explanation.is_used:
            return Response(
                {"error": "Explanation already submitted, cannot resend. Create a new explanation request."},
                status=status.HTTP_400_BAD_REQUEST,
            )

        # Generate new token
        import secrets

        new_token = secrets.token_urlsafe(32)
        explanation.token = new_token
        explanation.email_sent_at = timezone.now()
        explanation.save()

        # Determine recipient email
        if complaint.staff.user and complaint.staff.user.email:
            recipient_email = complaint.staff.user.email
            recipient_display = str(complaint.staff)
        elif complaint.staff.email:
            recipient_email = complaint.staff.email
            recipient_display = str(complaint.staff)
        else:
            return Response({"error": "Staff member has no email address"}, status=status.HTTP_400_BAD_REQUEST)

        # Send email with new link
        from django.contrib.sites.shortcuts import get_current_site
        from apps.notifications.services import NotificationService, get_email_header_html

        site = get_current_site(request)
        explanation_link = f"https://{site.domain}/complaints/{complaint.id}/explain/{new_token}/"

        # Build email subject
        subject = f"Explanation Request (Resent) - Complaint #{complaint.id}"

        # Build email body
        email_body = f"""
Dear {recipient_display},

We have resent the explanation request for the following complaint:

COMPLAINT DETAILS:
----------------
Reference: #{complaint.id}
Title: {complaint.title}
Severity: {complaint.get_severity_display()}
Priority: {complaint.get_priority_display()}
Status: {complaint.get_status_display()}

{complaint.description}
"""

        # Add patient info if available
        if complaint.patient:
            email_body += f"""
PATIENT INFORMATION:
------------------
Name: {complaint.patient.get_full_name()}
MRN: {complaint.patient.mrn}
"""

        email_body += f"""

SUBMIT YOUR EXPLANATION:
------------------------
Your perspective is important. Please submit your explanation about this complaint:
{explanation_link}

Note: This link can only be used once. After submission, it will expire.

If you have any questions, please contact PX team.

---
This is an automated message from PX360 Complaint Management System.
"""

        # Send email
        try:
            notification_log = NotificationService.send_email(
                email=recipient_email,
                subject=subject,
                message=email_body,
                html_message=f"""
<div style="font-family: 'Segoe UI', Tahoma, sans-serif; max-width: 600px; margin: 0 auto; border: 1px solid #e5e7eb; border-radius: 8px; overflow: hidden;">
    {get_email_header_html()}
    <div style="padding: 20px;">
        <h2 style="color: #005696; font-size: 18px; margin: 0 0 12px 0;">Explanation Request (Resent)</h2>
        <p style="margin: 0 0 12px 0;">Dear {recipient_display},</p>
        <p style="margin: 0 0 12px 0;">We have resent the explanation request for complaint <strong>#{complaint.id}</strong>:</p>
        <table style="width: 100%; border-collapse: collapse; margin: 0 0 12px 0;">
            <tr><td style="padding: 4px 0; color: #6b7280; width: 120px;">Title:</td><td style="padding: 4px 0;">{complaint.title}</td></tr>
            <tr><td style="padding: 4px 0; color: #6b7280;">Severity:</td><td style="padding: 4px 0;">{complaint.get_severity_display()}</td></tr>
            <tr><td style="padding: 4px 0; color: #6b7280;">Priority:</td><td style="padding: 4px 0;">{complaint.get_priority_display()}</td></tr>
        </table>
        <p style="margin: 0 0 6px 0; color: #6b7280; font-size: 13px;">This link can only be used once. After submission, it will expire.</p>
        <div style="text-align: center; margin: 20px 0;">
            <a href="{explanation_link}" style="background: #005696; color: white; padding: 10px 24px; border-radius: 8px; text-decoration: none; font-weight: 600;">Submit Explanation</a>
        </div>
    </div>
</div>
""",
                related_object=complaint,
                metadata={
                    "notification_type": "explanation_request_resent",
                    "recipient_type": "staff",
                    "staff_id": str(complaint.staff.id),
                    "explanation_id": str(explanation.id),
                    "requested_by_id": str(request.user.id),
                    "resent": True,
                },
            )
        except Exception as e:
            return Response({"error": f"Failed to send email: {str(e)}"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

        # Create ComplaintUpdate entry
        ComplaintUpdate.objects.create(
            complaint=complaint,
            update_type="communication",
            message=f"Explanation request resent to {recipient_display}",
            created_by=request.user,
            metadata={
                "explanation_id": str(explanation.id),
                "staff_id": str(complaint.staff.id),
                "notification_log_id": str(notification_log.id) if notification_log else None,
                "resent": True,
            },
        )

        # Log audit
        AuditService.log_from_request(
            event_type="explanation_resent",
            description=f"Explanation request resent to {recipient_display}",
            request=request,
            content_object=complaint,
            metadata={"explanation_id": str(explanation.id), "staff_id": str(complaint.staff.id)},
        )

        return Response(
            {
                "success": True,
                "message": "Explanation request resent successfully to staff member",
                "explanation_id": str(explanation.id),
                "recipient": recipient_display,
                "new_token": new_token,
                "explanation_link": explanation_link,
            },
            status=status.HTTP_200_OK,
        )

    @action(detail=True, methods=["post"])
    def send_explanation_reminder(self, request, pk=None):
        """
        Manually send first or second reminder for explanation request.

        Allows admin to trigger a reminder email when the automated task didn't run.
        """
        complaint = self.get_object()

        if not complaint.is_active_status:
            return Response(
                {"error": f"Cannot send reminder for complaint with status '{complaint.get_status_display()}'."},
                status=status.HTTP_400_BAD_REQUEST,
            )

        explanation_id = request.data.get("explanation_id")
        reminder_type = request.data.get("reminder_type", "first")

        if not explanation_id:
            return Response({"error": "explanation_id is required"}, status=status.HTTP_400_BAD_REQUEST)

        try:
            explanation = ComplaintExplanation.objects.get(pk=explanation_id, complaint=complaint)
        except ComplaintExplanation.DoesNotExist:
            return Response({"error": "Explanation not found"}, status=status.HTTP_404_NOT_FOUND)

        if explanation.is_used:
            return Response({"error": "Explanation already submitted"}, status=status.HTTP_400_BAD_REQUEST)

        if reminder_type not in ("first", "second"):
            return Response({"error": "reminder_type must be 'first' or 'second'"}, status=status.HTTP_400_BAD_REQUEST)

        if reminder_type == "first":
            if explanation.reminder_sent_at:
                return Response({"error": "First reminder already sent"}, status=status.HTTP_400_BAD_REQUEST)
        else:
            if not explanation.reminder_sent_at:
                return Response(
                    {"error": "First reminder must be sent before second reminder"},
                    status=status.HTTP_400_BAD_REQUEST,
                )
            if explanation.second_reminder_sent_at:
                return Response({"error": "Second reminder already sent"}, status=status.HTTP_400_BAD_REQUEST)

        if not explanation.staff.email:
            return Response({"error": "Staff member has no email address"}, status=status.HTTP_400_BAD_REQUEST)

        now = timezone.now()
        hours_remaining = 0
        if explanation.sla_due_at:
            hours_remaining = max(0, int((explanation.sla_due_at - now).total_seconds() / 3600))

        context = {
            "explanation": explanation,
            "complaint": complaint,
            "staff": explanation.staff,
            "hours_remaining": hours_remaining,
            "due_date": explanation.sla_due_at,
            "site_url": request.build_absolute_uri("/").rstrip("/"),
        }

        if reminder_type == "first":
            subject = f"Reminder: Explanation Request - Complaint #{str(complaint.id)[:8]}"
            try:
                from django.template.loader import render_to_string
                from django.core.mail import send_mail
                from django.conf import settings

                message_en = render_to_string("complaints/emails/explanation_reminder_en.txt", context)
                message_ar = render_to_string("complaints/emails/explanation_reminder_ar.txt", context)
                html_message = render_to_string("emails/explanation_reminder.html", context)

                send_mail(
                    subject=subject,
                    message=f"{message_en}\n\n{message_ar}",
                    from_email=settings.DEFAULT_FROM_EMAIL,
                    recipient_list=[explanation.staff.email],
                    fail_silently=False,
                    html_message=html_message,
                )

                explanation.reminder_sent_at = now
                explanation.save(update_fields=["reminder_sent_at"])
            except Exception as e:
                return Response(
                    {"error": f"Failed to send reminder: {str(e)}"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR
                )
        else:
            subject = f"URGENT - Final Reminder: Explanation Request - Complaint #{str(complaint.id)[:8]}"
            try:
                from django.template.loader import render_to_string
                from django.core.mail import send_mail
                from django.conf import settings

                message_en = render_to_string("complaints/emails/explanation_second_reminder_en.txt", context)
                message_ar = render_to_string("complaints/emails/explanation_second_reminder_ar.txt", context)
                html_message = render_to_string("emails/explanation_second_reminder.html", context)

                send_mail(
                    subject=subject,
                    message=f"{message_en}\n\n{message_ar}",
                    from_email=settings.DEFAULT_FROM_EMAIL,
                    recipient_list=[explanation.staff.email],
                    fail_silently=False,
                    html_message=html_message,
                )

                explanation.second_reminder_sent_at = now
                explanation.save(update_fields=["second_reminder_sent_at"])
            except Exception as e:
                return Response(
                    {"error": f"Failed to send reminder: {str(e)}"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR
                )

        label = "first" if reminder_type == "first" else "second"
        recipient_display = str(explanation.staff)

        ComplaintUpdate.objects.create(
            complaint=complaint,
            update_type="communication",
            message=f"{label.capitalize()} explanation reminder sent to {recipient_display}",
            created_by=request.user,
            metadata={
                "explanation_id": str(explanation.id),
                "staff_id": str(explanation.staff.id),
                "reminder_type": reminder_type,
            },
        )

        AuditService.log_from_request(
            event_type=f"explanation_{label}_reminder_sent",
            description=f"{label.capitalize()} explanation reminder sent to {recipient_display}",
            request=request,
            content_object=complaint,
            metadata={"explanation_id": str(explanation.id), "staff_id": str(explanation.staff.id)},
        )

        return Response(
            {
                "success": True,
                "message": f"{label.capitalize()} reminder sent to {recipient_display}",
                "explanation_id": str(explanation.id),
                "reminder_type": reminder_type,
            },
            status=status.HTTP_200_OK,
        )

    @action(detail=True, methods=["post"])
    def review_explanation(self, request, pk=None):
        """
        Review and mark an explanation as acceptable or not acceptable.

        Allows PX Admins to review submitted explanations and mark them.
        """
        complaint = self.get_object()

        # Check permission
        if not (request.user.is_px_admin() or request.user.is_hospital_admin()):
            return Response(
                {"error": "Only PX Admins or Hospital Admins can review explanations"}, status=status.HTTP_403_FORBIDDEN
            )

        explanation_id = request.data.get("explanation_id")
        acceptance_status = request.data.get("acceptance_status")
        acceptance_notes = request.data.get("acceptance_notes", "")

        if not explanation_id:
            return Response({"error": "explanation_id is required"}, status=status.HTTP_400_BAD_REQUEST)

        if not acceptance_status:
            return Response(
                {"error": "acceptance_status is required (acceptable or not_acceptable)"},
                status=status.HTTP_400_BAD_REQUEST,
            )

        # Validate acceptance status
        from .models import ComplaintExplanation

        valid_statuses = [
            ComplaintExplanation.AcceptanceStatus.ACCEPTABLE,
            ComplaintExplanation.AcceptanceStatus.NOT_ACCEPTABLE,
        ]
        if acceptance_status not in valid_statuses:
            return Response(
                {"error": f"Invalid acceptance_status. Must be one of: {valid_statuses}"},
                status=status.HTTP_400_BAD_REQUEST,
            )

        # Get the explanation
        try:
            explanation = ComplaintExplanation.objects.get(id=explanation_id, complaint=complaint)
        except ComplaintExplanation.DoesNotExist:
            return Response({"error": "Explanation not found"}, status=status.HTTP_404_NOT_FOUND)

        # Check if explanation has been submitted
        if not explanation.is_used:
            return Response(
                {"error": "Cannot review explanation that has not been submitted yet"},
                status=status.HTTP_400_BAD_REQUEST,
            )

        # Update explanation
        explanation.acceptance_status = acceptance_status
        explanation.accepted_by = request.user
        explanation.accepted_at = timezone.now()
        explanation.acceptance_notes = acceptance_notes
        explanation.save()

        # Create complaint update
        status_display = (
            "Acceptable" if acceptance_status == ComplaintExplanation.AcceptanceStatus.ACCEPTABLE else "Not Acceptable"
        )
        ComplaintUpdate.objects.create(
            complaint=complaint,
            update_type="note",
            message=f"Explanation from {explanation.staff} marked as {status_display}",
            created_by=request.user,
            metadata={
                "explanation_id": str(explanation.id),
                "staff_id": str(explanation.staff.id) if explanation.staff else None,
                "acceptance_status": acceptance_status,
                "acceptance_notes": acceptance_notes,
            },
        )

        # Log audit
        AuditService.log_from_request(
            event_type="explanation_reviewed",
            description=f"Explanation marked as {status_display}",
            request=request,
            content_object=explanation,
            metadata={
                "explanation_id": str(explanation.id),
                "acceptance_status": acceptance_status,
                "acceptance_notes": acceptance_notes,
            },
        )

        return Response(
            {
                "success": True,
                "message": f"Explanation marked as {status_display}",
                "explanation_id": str(explanation.id),
                "acceptance_status": acceptance_status,
                "accepted_at": explanation.accepted_at,
                "accepted_by": request.user.get_full_name(),
            }
        )

    @action(detail=True, methods=["post"])
    def escalate_explanation(self, request, pk=None):
        """
        Escalate an explanation to the staff's manager.

        Marks the explanation as not acceptable and sends an explanation request
        to the staff's manager (report_to).
        """
        complaint = self.get_object()
        # Check permission
        if not (request.user.is_px_admin() or request.user.is_hospital_admin()):
            return Response(
                {"error": "Only PX Admins or Hospital Admins can escalate explanations"},
                status=status.HTTP_403_FORBIDDEN,
            )

        explanation_id = request.data.get("explanation_id")
        acceptance_notes = request.data.get("acceptance_notes", "")

        if not explanation_id:
            return Response({"error": "explanation_id is required"}, status=status.HTTP_400_BAD_REQUEST)

        # Get the explanation
        try:
            explanation = ComplaintExplanation.objects.select_related("staff", "staff__report_to").get(
                id=explanation_id, complaint=complaint
            )
        except ComplaintExplanation.DoesNotExist:
            return Response({"error": "Explanation not found"}, status=status.HTTP_404_NOT_FOUND)

        # Check if explanation has been submitted
        if not explanation.is_used:
            return Response(
                {"error": "Cannot escalate explanation that has not been submitted yet"},
                status=status.HTTP_400_BAD_REQUEST,
            )

        # Check if already escalated
        if explanation.escalated_to_manager:
            return Response({"error": "Explanation has already been escalated"}, status=status.HTTP_400_BAD_REQUEST)

        # Use fallback chain to find escalation target
        from apps.complaints.services.complaint_service import ComplaintService
        from apps.organizations.models import Staff

        target_user, fallback_path = ComplaintService.get_escalation_target(complaint, staff=explanation.staff)

        if not target_user:
            return Response(
                {"error": f"No escalation target found (tried: {fallback_path})"},
                status=status.HTTP_400_BAD_REQUEST,
            )

        manager = Staff.objects.filter(user=target_user).first()

        if not manager:
            return Response(
                {"error": f"Escalation target {target_user.get_full_name()} has no Staff record"},
                status=status.HTTP_400_BAD_REQUEST,
            )

        # Check if manager already has an explanation request for this complaint
        existing_manager_explanation = ComplaintExplanation.objects.filter(complaint=complaint, staff=manager).first()

        if existing_manager_explanation:
            return Response(
                {"error": f"Manager {manager.get_full_name()} already has an explanation request for this complaint"},
                status=status.HTTP_400_BAD_REQUEST,
            )

        # Generate token for manager explanation
        import secrets

        manager_token = secrets.token_urlsafe(32)

        request_message = f"Escalated from staff explanation. Staff: {explanation.staff.get_full_name() if explanation.staff else 'Unknown'}. Notes: {acceptance_notes}"
        if fallback_path != "staff.report_to":
            request_message += f" [Escalated via fallback: {fallback_path}]"

        # Create manager explanation record
        manager_explanation = ComplaintExplanation.objects.create(
            complaint=complaint,
            staff=manager,
            token=manager_token,
            is_used=False,
            requested_by=request.user,
            request_message=request_message,
            submitted_via="email_link",
            email_sent_at=timezone.now(),
            metadata={
                "escalation_fallback_path": fallback_path,
            },
        )

        # Update original explanation
        explanation.acceptance_status = ComplaintExplanation.AcceptanceStatus.NOT_ACCEPTABLE
        explanation.accepted_by = request.user
        explanation.accepted_at = timezone.now()
        explanation.acceptance_notes = acceptance_notes
        explanation.escalated_to_manager = manager_explanation
        explanation.escalated_at = timezone.now()
        explanation.save()

        # Send email to manager
        from django.contrib.sites.shortcuts import get_current_site
        from apps.notifications.services import NotificationService, get_email_header_html

        site = get_current_site(request)
        explanation_link = f"https://{site.domain}/complaints/{complaint.id}/explain/{manager_token}/"

        manager_email = manager.email or (manager.user.email if manager.user else None)

        if manager_email:
            subject = f"Escalated Explanation Request - Complaint #{complaint.reference_number}"

            email_body = f"""Dear {manager.get_full_name()},

An explanation submitted by a staff member who reports to you has been marked as not acceptable and escalated to you for further review.

STAFF MEMBER:
------------
Name: {explanation.staff.get_full_name() if explanation.staff else "Unknown"}
Employee ID: {explanation.staff.employee_id if explanation.staff else "N/A"}
Department: {explanation.staff.department.name if explanation.staff and explanation.staff.department else "N/A"}

COMPLAINT DETAILS:
----------------
Reference: {complaint.reference_number}
Title: {complaint.title}
Severity: {complaint.get_severity_display()}
Priority: {complaint.get_priority_display()}

ORIGINAL EXPLANATION (Not Acceptable):
--------------------------------------
{explanation.explanation}

ESCALATION NOTES:
-----------------
{acceptance_notes if acceptance_notes else "No additional notes provided."}

PLEASE SUBMIT YOUR EXPLANATION:
------------------------------
As the manager, please submit your perspective on this matter:
{explanation_link}

Note: This link can only be used once. After submission, it will expire.

---
This is an automated message from PX360 Complaint Management System.
"""

            try:
                NotificationService.send_email(
                    email=manager_email,
                    subject=subject,
                    message=email_body,
                    html_message=f"""
<div style="font-family: 'Segoe UI', Tahoma, sans-serif; max-width: 600px; margin: 0 auto; border: 1px solid #e5e7eb; border-radius: 8px; overflow: hidden;">
    {get_email_header_html()}
    <div style="padding: 20px;">
        <h2 style="color: #005696; font-size: 18px; margin: 0 0 12px 0;">Escalated Explanation Request</h2>
        <p style="margin: 0 0 12px 0;">The original explanation was not acceptable and this request has been escalated to you for review.</p>
        <table style="width: 100%; border-collapse: collapse; margin: 0 0 12px 0;">
            <tr><td style="padding: 4px 0; color: #6b7280; width: 140px;">Reference:</td><td style="padding: 4px 0;"><strong>{complaint.reference_number}</strong></td></tr>
            <tr><td style="padding: 4px 0; color: #6b7280;">Title:</td><td style="padding: 4px 0;">{complaint.title}</td></tr>
            <tr><td style="padding: 4px 0; color: #6b7280;">Severity:</td><td style="padding: 4px 0;">{complaint.get_severity_display()}</td></tr>
            <tr><td style="padding: 4px 0; color: #6b7280;">Priority:</td><td style="padding: 4px 0;">{complaint.get_priority_display()}</td></tr>
        </table>
        <p style="margin: 0 0 6px 0; color: #6b7280; font-size: 13px;">This link can only be used once. After submission, it will expire.</p>
        <div style="text-align: center; margin: 20px 0;">
            <a href="{explanation_link}" style="background: #005696; color: white; padding: 10px 24px; border-radius: 8px; text-decoration: none; font-weight: 600;">Submit Your Explanation</a>
        </div>
    </div>
</div>
""",
                    related_object=complaint,
                    metadata={
                        "notification_type": "escalated_explanation_request",
                        "manager_id": str(manager.id),
                        "staff_id": str(explanation.staff.id) if explanation.staff else None,
                        "complaint_id": str(complaint.id),
                        "original_explanation_id": str(explanation.id),
                    },
                )
                email_sent = True
            except Exception as e:
                logger.error(f"Failed to send escalation email to manager: {e}")
                email_sent = False
        else:
            email_sent = False

        # Create complaint update
        ComplaintUpdate.objects.create(
            complaint=complaint,
            update_type="note",
            message=f"Explanation from {explanation.staff} marked as Not Acceptable and escalated to manager {manager.get_full_name()}",
            created_by=request.user,
            metadata={
                "explanation_id": str(explanation.id),
                "staff_id": str(explanation.staff.id) if explanation.staff else None,
                "manager_id": str(manager.id),
                "manager_explanation_id": str(manager_explanation.id),
                "acceptance_status": "not_acceptable",
                "acceptance_notes": acceptance_notes,
                "email_sent": email_sent,
            },
        )

        # Log audit
        AuditService.log_from_request(
            event_type="explanation_escalated",
            description=f"Explanation escalated to manager {manager.get_full_name()}",
            request=request,
            content_object=explanation,
            metadata={
                "explanation_id": str(explanation.id),
                "manager_id": str(manager.id),
                "manager_explanation_id": str(manager_explanation.id),
                "email_sent": email_sent,
            },
        )

        return Response(
            {
                "success": True,
                "message": f"Explanation escalated to manager {manager.get_full_name()}",
                "explanation_id": str(explanation.id),
                "manager_explanation_id": str(manager_explanation.id),
                "manager_name": manager.get_full_name(),
                "manager_email": manager_email,
                "email_sent": email_sent,
            }
        )

    @action(detail=True, methods=["post"])
    def generate_ai_resolution(self, request, pk=None):
        """
        Generate AI-powered resolution note based on complaint details and explanations.

        Analyzes the complaint description, staff explanations, and manager explanations
        to generate a comprehensive resolution note for admin review.
        """
        complaint = self.get_object()

        # Check permission - same logic as can_manage_complaint
        user = request.user
        can_generate = (
            user.is_px_admin()
            or (user.is_hospital_admin() and user.hospital == complaint.hospital)
            or (user.is_department_manager() and user.department == complaint.department)
            or complaint.assigned_to == user
        )

        if not can_generate:
            return Response(
                {"error": "You do not have permission to generate AI resolution for this complaint"},
                status=status.HTTP_403_FORBIDDEN,
            )

        # Get all used explanations
        explanations = complaint.explanations.filter(is_used=True).select_related("staff")

        if not explanations.exists():
            return Response(
                {"success": False, "error": "No explanations available to analyze. Please request explanations first."},
                status=status.HTTP_400_BAD_REQUEST,
            )

        # Build context for AI
        context = {
            "complaint": {
                "title": complaint.title,
                "description": complaint.description,
                "severity": complaint.get_severity_display(),
                "priority": complaint.get_priority_display(),
                "patient_name": complaint.patient.get_full_name() if complaint.patient else "Unknown",
                "department": complaint.department.name if complaint.department else "Unknown",
            },
            "explanations": [],
        }

        for exp in explanations:
            exp_data = {
                "staff_name": exp.staff.get_full_name() if exp.staff else "Unknown",
                "employee_id": exp.staff.employee_id if exp.staff else "N/A",
                "department": exp.staff.department.name if exp.staff and exp.staff.department else "N/A",
                "explanation": exp.explanation,
                "acceptance_status": exp.get_acceptance_status_display(),
                "submitted_at": exp.responded_at.strftime("%Y-%m-%d %H:%M") if exp.responded_at else "Unknown",
            }
            context["explanations"].append(exp_data)

        # Call AI service to generate resolution
        try:
            from apps.core.ai_service import AIService

            # Build prompt
            explanations_text = ""
            for i, exp in enumerate(context["explanations"], 1):
                explanations_text += f"""
Explanation {i}:
- Staff: {exp["staff_name"]} (ID: {exp["employee_id"]}, Dept: {exp["department"]})
- Status: {exp["acceptance_status"]}
- Submitted: {exp["submitted_at"]}
- Content: {exp["explanation"]}

"""

            prompt = f"""As a healthcare complaint resolution expert, analyze the following complaint and staff explanations to generate a comprehensive resolution note in BOTH English and Arabic.

COMPLAINT DETAILS:
- Title: {context["complaint"]["title"]}
- Description: {context["complaint"]["description"]}
- Severity: {context["complaint"]["severity"]}
- Priority: {context["complaint"]["priority"]}
- Patient: {context["complaint"]["patient_name"]}
- Department: {context["complaint"]["department"]}

STAFF EXPLANATIONS:
{explanations_text}

Based on the above information, generate a professional resolution note that:
1. Summarizes the main issue and root cause
2. References the key points from staff explanations
3. States the outcome/decision
4. Includes any corrective actions taken or planned
5. Addresses patient concerns
6. Mentions any follow-up actions

The resolution should be written in a professional, empathetic tone suitable for healthcare settings.

IMPORTANT: Provide the resolution in BOTH languages as JSON:
{{
    "resolution_en": "The resolution text in English (3-5 paragraphs)",
    "resolution_ar": "نص القرار بالعربية (3-5 فقرات)"
}}

Ensure both versions convey the same meaning and are professionally written."""

            system_prompt = """You are an expert healthcare complaint resolution specialist fluent in both English and Arabic.
Your task is to analyze complaints and staff explanations to generate comprehensive, professional resolution notes in both languages.
Be objective, empathetic, and thorough. Focus on facts while acknowledging the patient's concerns.
Write in a professional tone appropriate for medical records in both languages.
Always provide valid JSON output with both resolution_en and resolution_ar fields."""

            ai_response = AIService.chat_completion(
                prompt=prompt,
                system_prompt=system_prompt,
                temperature=0.4,
                max_tokens=1500,
                response_format="json_object",
            )

            # Parse the JSON response
            import json

            resolution_data = json.loads(ai_response)
            resolution_en = resolution_data.get("resolution_en", "").strip()
            resolution_ar = resolution_data.get("resolution_ar", "").strip()

            # Log the AI generation
            AuditService.log_from_request(
                event_type="ai_resolution_generated",
                description=f"AI resolution generated for complaint {complaint.reference_number}",
                request=request,
                content_object=complaint,
                metadata={
                    "complaint_id": str(complaint.id),
                    "explanation_count": explanations.count(),
                    "generated_resolution_en_length": len(resolution_en),
                    "generated_resolution_ar_length": len(resolution_ar),
                },
            )

            return Response(
                {
                    "success": True,
                    "resolution_en": resolution_en,
                    "resolution_ar": resolution_ar,
                    "explanation_count": explanations.count(),
                }
            )

        except Exception as e:
            logger.error(f"AI resolution generation failed: {e}")
            return Response(
                {"success": False, "error": f"Failed to generate resolution: {str(e)}"},
                status=status.HTTP_500_INTERNAL_SERVER_ERROR,
            )

    @action(detail=True, methods=["get"])
    def generate_resolution_suggestion(self, request, pk=None):
        """
        Generate AI resolution suggestion based on complaint and acceptable explanation.

        Uses the staff explanation if acceptable, otherwise uses manager explanation.
        Returns a suggested resolution text that can be edited or used directly.
        """
        complaint = self.get_object()

        # Check permission
        if not (request.user.is_px_admin() or request.user.is_hospital_admin()):
            return Response(
                {"error": "Only PX Admins or Hospital Admins can generate resolution suggestions"},
                status=status.HTTP_403_FORBIDDEN,
            )

        # Find acceptable explanation
        acceptable_explanation = None
        explanation_source = None

        # First, try to find an acceptable staff explanation
        staff_explanation = complaint.explanations.filter(
            staff=complaint.staff, is_used=True, acceptance_status=ComplaintExplanation.AcceptanceStatus.ACCEPTABLE
        ).first()

        if staff_explanation:
            acceptable_explanation = staff_explanation
            explanation_source = "staff"
        else:
            # Try to find an acceptable manager explanation (escalated)
            manager_explanation = complaint.explanations.filter(
                is_used=True,
                acceptance_status=ComplaintExplanation.AcceptanceStatus.ACCEPTABLE,
                metadata__is_escalation=True,
            ).first()

            if manager_explanation:
                acceptable_explanation = manager_explanation
                explanation_source = "manager"

        if not acceptable_explanation:
            return Response(
                {
                    "error": "No acceptable explanation found. Please review and mark an explanation as acceptable first.",
                    "suggestion": None,
                },
                status=status.HTTP_400_BAD_REQUEST,
            )

        # Generate resolution using AI
        try:
            resolution_text = self._generate_ai_resolution(
                complaint=complaint, explanation=acceptable_explanation, source=explanation_source
            )

            return Response(
                {
                    "success": True,
                    "suggestion": resolution_text,
                    "source": explanation_source,
                    "source_staff": acceptable_explanation.staff.get_full_name()
                    if acceptable_explanation.staff
                    else None,
                    "explanation_id": str(acceptable_explanation.id),
                }
            )

        except Exception as e:
            logger.error(f"Failed to generate resolution: {e}")
            return Response(
                {"error": "Failed to generate resolution suggestion", "detail": str(e)},
                status=status.HTTP_500_INTERNAL_SERVER_ERROR,
            )

    def _generate_ai_resolution(self, complaint, explanation, source):
        explanation_text = explanation.explanation
        explanation_by = explanation.staff.get_full_name() if explanation.staff else "Unknown"

        try:
            from apps.core.ai_service import AIService

            prompt = f"""Based on the following complaint and investigation, generate a professional resolution summary that will be sent to the patient. The response should be empathetic, clear, and describe the actions taken.

Complaint: {complaint.description[:1000]}
Severity: {complaint.get_severity_display()}
Category: {complaint.category.get_localized_name() if complaint.category else 'N/A'}
Explanation by {explanation_by} ({source}): {explanation_text[:1000]}

Generate a JSON response with:
- "resolution_en": Professional resolution summary in English (2-3 paragraphs)
- "resolution_ar": Same resolution in Arabic"""

            result = AIService.chat_completion(
                prompt=prompt,
                response_format="json_object",
            )
            import json

            parsed = json.loads(result)
            return parsed.get("resolution_en", result)
        except Exception as e:
            logger.warning(f"AI resolution generation failed, using template: {e}")

        return f"""Based on the complaint filed regarding: {complaint.title}

After reviewing the complaint and the explanation provided by {explanation_by} ({source}), the following has been determined:

{explanation_text}

The matter has been addressed through appropriate channels. Appropriate measures have been implemented to address the concern and steps have been taken to prevent recurrence. The complaint is considered resolved."""

    @action(detail=True, methods=["get"])
    def ai_helper_suggestions(self, request, pk=None):
        complaint = self.get_object()

        if not (request.user.is_px_admin or request.user.is_hospital_admin()):
            return Response({"error": "Permission denied"}, status=status.HTTP_403_FORBIDDEN)

        try:
            from apps.core.ai_service import AIService
            import json

            explanations_text = ""
            for exp in complaint.explanations.filter(is_used=True):
                name = exp.staff.get_full_name() if exp.staff else "Staff"
                explanations_text += f"\n- {name}: {exp.explanation[:500]}"

            prompt = f"""You are a patient experience resolution advisor. Based on this complaint, provide actionable suggestions for resolving it.

Complaint: {complaint.description[:1500]}
Severity: {complaint.get_severity_display()}
Category: {complaint.category.get_localized_name() if complaint.category else 'N/A'}
Priority: {complaint.get_priority_display()}
Status: {complaint.get_status_display()}
Staff explanations received: {explanations_text or 'None yet'}

Generate a JSON response with:
- "suggestions": array of 3-5 actionable suggestions, each with "title" and "description"
- "recommended_actions": array of immediate next steps
- "communication_tip": a tip for communicating with the patient"""

            result = AIService.chat_completion(
                prompt=prompt,
                response_format="json_object",
            )
            parsed = json.loads(result)

            return Response({"success": True, "suggestions": parsed})
        except Exception as e:
            logger.error(f"AI helper suggestion failed: {e}")
            return Response({"error": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    def _get_pdf_context_data(self, complaint):
        """Compute all PDF template context fields from DB data."""
        from apps.complaints.models import ComplaintInvolvedDepartment, ComplaintInvolvedStaff

        def fmt_date_ar(dt):
            if not dt:
                return "—"
            return dt.strftime("%Y/%m/%d %p %I:%M").replace("AM", "ص").replace("PM", "م")

        hospital_name = (
            complaint.hospital.get_display_name_ar()
            if complaint.hospital and complaint.hospital.get_display_name_ar()
            else complaint.hospital.get_display_name() if complaint.hospital else ""
        )
        dept_name = (
            complaint.department.name_ar
            if complaint.department and complaint.department.name_ar
            else complaint.department.name_en or complaint.department.name if complaint.department else ""
        )
        complainant_name = (
            complaint.contact_name
            or complaint.patient_name
            or (complaint.patient.get_full_name() if complaint.patient else "")
        )
        source_name = complaint.source.name_ar if complaint.source else ""

        accused = ComplaintInvolvedStaff.objects.filter(
            complaint=complaint, role="accused"
        ).select_related("staff", "staff__department").first()

        accused_staff_name = ""
        accused_staff_title = ""
        if accused and accused.staff:
            s = accused.staff
            accused_staff_name = s.name_ar or s.name or f"{s.first_name} {s.last_name}"
            accused_staff_title = s.job_title or ""

        sent_to_dept_at = complaint.sent_to_department_at or complaint.forwarded_to_dept_at

        first_response_dept = ComplaintInvolvedDepartment.objects.filter(
            complaint=complaint, response_submitted=True
        ).order_by("response_submitted_at").first()
        response_submitted_at = first_response_dept.response_submitted_at if first_response_dept else None

        return {
            "hospital_name": hospital_name,
            "department_name": dept_name,
            "complainant_name": complainant_name,
            "source_name": source_name,
            "accused_staff_name": accused_staff_name,
            "accused_staff_title": accused_staff_title,
            "submission_date": fmt_date_ar(complaint.created_at),
            "incident_date": complaint.incident_date.strftime("%Y/%m/%d") if complaint.incident_date else "—",
            "sent_to_dept_date": fmt_date_ar(sent_to_dept_at),
            "response_date": fmt_date_ar(response_submitted_at),
        }

    @action(detail=True, methods=["get", "post"])
    def summary_preview(self, request, pk=None):
        """Get existing summary (GET) or generate AI preview (POST)."""
        complaint = self.get_object()

        user = request.user
        can_generate = (
            user.is_px_admin()
            or (user.is_hospital_admin() and user.hospital == complaint.hospital)
            or (user.is_department_manager() and user.department == complaint.department)
            or (user.is_px_employee and complaint.hospital == user.hospital)
        )
        if not can_generate:
            return Response(
                {"error": "You do not have permission to generate a PDF summary"},
                status=status.HTTP_403_FORBIDDEN,
            )

        from .models import ComplaintPdfSummary

        if request.method == "GET":
            ctx = self._get_pdf_context_data(complaint)
            summary = ComplaintPdfSummary.objects.filter(complaint=complaint).first()
            if summary:
                data = {
                    "exists": True,
                    "content_summary": summary.content_summary,
                    "dept_response_summary": summary.dept_response_summary,
                    **ctx,
                }
                if summary.file:
                    data["has_file"] = True
                    data["file_url"] = summary.file.url
                else:
                    data["has_file"] = False
                return Response(data)
            return Response({"exists": False, **ctx})

        try:
            import json

            from apps.complaints.models import ComplaintInvolvedDepartment

            dept_response_parts = []
            involved_depts = ComplaintInvolvedDepartment.objects.filter(
                complaint=complaint
            ).select_related("department")
            for dept in involved_depts:
                resp = dept.response_notes_ar or dept.response_notes_en or dept.response_notes or ""
                resp = resp[:600]
                d_name = dept.department.name_ar or dept.department.name_en or dept.department.name
                if resp:
                    dept_response_parts.append(f"- {d_name}: {resp}")

            if not dept_response_parts and complaint.action_taken_by_dept:
                dept_response_parts.append(complaint.action_taken_by_dept[:600])

            dept_response_text = "\n".join(dept_response_parts) or "No department response recorded."
            resolution_text = complaint.resolution or complaint.recommendation_action_plan or ""

            prompt = f"""You are a healthcare complaint report writer. Generate your response entirely in Modern Standard Arabic (Fusha).

COMPLAINT:
- Title: {complaint.title}
- Description: {complaint.description[:2000]}

DEPARTMENT RESPONSE / ACTIONS TAKEN:
{dept_response_text}

RESOLUTION:
{resolution_text[:600] or 'No resolution recorded.'}

Generate JSON with exactly these fields:
- "content_summary": 2-3 paragraph professional summary of the complaint content.
- "department_response_summary": 1-2 paragraph summary of the department response and actions taken."""

            from apps.core.ai_service import AIService

            result = AIService.chat_completion(
                prompt=prompt,
                response_format="json_object",
                temperature=0.3,
                max_tokens=1500,
            )
            parsed = json.loads(result)

            content_summary = parsed.get(
                "content_summary", complaint.description[:500] if complaint.description else ""
            )
            dept_response_summary = parsed.get(
                "department_response_summary",
                complaint.action_taken_by_dept[:500] if complaint.action_taken_by_dept else "",
            )

            ComplaintPdfSummary.objects.update_or_create(
                complaint=complaint,
                defaults={
                    "lang": "ar",
                    "content_summary": content_summary,
                    "dept_response_summary": dept_response_summary,
                },
            )

            ctx = self._get_pdf_context_data(complaint)

            return Response({
                "content_summary": content_summary,
                "dept_response_summary": dept_response_summary,
                **ctx,
            })

        except Exception as e:
            logger.error(f"Error generating summary preview for complaint {pk}: {e}")
            return Response({"error": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    @action(detail=True, methods=["post"])
    def generate_summary_pdf(self, request, pk=None):
        """Generate a PDF report for the complaint in the requested language (en/ar)."""
        complaint = self.get_object()

        user = request.user
        can_generate = (
            user.is_px_admin()
            or (user.is_hospital_admin() and user.hospital == complaint.hospital)
            or (user.is_department_manager() and user.department == complaint.department)
            or (user.is_px_employee and complaint.hospital == user.hospital)
        )
        if not can_generate:
            return Response(
                {"error": "You do not have permission to generate a PDF summary"},
                status=status.HTTP_403_FORBIDDEN,
            )

        try:
            import base64
            import json

            from django.conf import settings
            from django.template.loader import render_to_string

            lang = request.data.get("lang", "ar")

            from apps.complaints.models import ComplaintInvolvedDepartment

            dept_response_parts = []
            involved_depts = ComplaintInvolvedDepartment.objects.filter(
                complaint=complaint
            ).select_related("department")
            for dept in involved_depts:
                resp = dept.response_notes_ar or dept.response_notes_en or dept.response_notes or ""
                resp = resp[:600]
                d_name = dept.department.name_ar or dept.department.name_en or dept.department.name
                if resp:
                    dept_response_parts.append(f"- {d_name}: {resp}")

            if not dept_response_parts and complaint.action_taken_by_dept:
                dept_response_parts.append(complaint.action_taken_by_dept[:600])

            dept_response_text = "\n".join(dept_response_parts) or "No department response recorded."

            resolution_text = complaint.resolution or complaint.recommendation_action_plan or ""

            # Use pre-written text from request, then saved summary, then AI fallback
            content_summary = request.data.get("content_summary")
            dept_response_summary = request.data.get("dept_response_summary")

            if not content_summary or not dept_response_summary:
                from .models import ComplaintPdfSummary
                saved = ComplaintPdfSummary.objects.filter(complaint=complaint).first()
                if saved and saved.content_summary and saved.dept_response_summary:
                    content_summary = saved.content_summary
                    dept_response_summary = saved.dept_response_summary
                else:
                    import json

                    prompt = f"""You are a healthcare complaint report writer. Generate your response entirely in Modern Standard Arabic (Fusha).

COMPLAINT:
- Title: {complaint.title}
- Description: {complaint.description[:2000]}

DEPARTMENT RESPONSE / ACTIONS TAKEN:
{dept_response_text}

RESOLUTION:
{resolution_text[:600] or 'No resolution recorded.'}

Generate JSON with exactly these fields:
- "content_summary": 2-3 paragraph professional summary of the complaint content.
- "department_response_summary": 1-2 paragraph summary of the department response and actions taken."""

                    from apps.core.ai_service import AIService

                    result = AIService.chat_completion(
                        prompt=prompt,
                        response_format="json_object",
                        temperature=0.3,
                        max_tokens=1500,
                    )
                    parsed = json.loads(result)

                    content_summary = parsed.get("content_summary", complaint.description[:500] if complaint.description else "")
                    dept_response_summary = parsed.get(
                        "department_response_summary",
                        complaint.action_taken_by_dept[:500] if complaint.action_taken_by_dept else "",
                    )

            ctx = self._get_pdf_context_data(complaint)

            for field in ["complainant_name", "source_name", "department_name",
                          "accused_staff_name", "accused_staff_title",
                          "submission_date", "incident_date",
                          "sent_to_dept_date", "response_date"]:
                val = request.data.get(field)
                if val:
                    ctx[field] = val

            import io
            from PIL import Image as PILImage
            _logo_img = PILImage.open(settings.BASE_DIR / "static" / "img" / "HH_P_V_Logo(hospital)_.png")
            _logo_img.thumbnail((600, 600), PILImage.LANCZOS)
            _logo_buf = io.BytesIO()
            _logo_img.save(_logo_buf, format="PNG", optimize=True)
            logo_path = "data:image/png;base64," + base64.b64encode(_logo_buf.getvalue()).decode()

            html_string = render_to_string(
                "complaints/complaint_summary_pdf.html",
                {
                    "complaint": complaint,
                    "lang": "ar",
                    "content_summary": content_summary,
                    "dept_response_summary": dept_response_summary,
                    "logo_path": logo_path,
                    "hospital_name_en": complaint.hospital.get_display_name() if complaint.hospital else "",
                    "hospital_address": complaint.hospital.address if complaint.hospital else "",
                    "hospital_phone": complaint.hospital.phone if complaint.hospital else "",
                    "hospital_email": complaint.hospital.email if complaint.hospital else "",
                    **ctx,
                },
            )

            from weasyprint import HTML

            pdf_file = HTML(string=html_string, base_url=str(settings.BASE_DIR / "static")).write_pdf()

            # Save PDF to persistent storage
            from django.core.files.base import ContentFile
            from .models import ComplaintPdfSummary
            summary, _ = ComplaintPdfSummary.objects.update_or_create(
                complaint=complaint,
                defaults={
                    "lang": "ar",
                    "content_summary": content_summary,
                    "dept_response_summary": dept_response_summary,
                },
            )
            summary.file.save(f"{complaint.pk}_ar.pdf", ContentFile(pdf_file), save=False)
            summary.file_size = len(pdf_file)
            summary.save()

            from django.http import HttpResponse
            from datetime import datetime

            timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
            filename = f"complaint_summary_{complaint.reference_number}_ar_{timestamp}.pdf"

            response = HttpResponse(pdf_file, content_type="application/pdf")
            response["Content-Disposition"] = f'attachment; filename="{filename}"'

            AuditService.log_from_request(
                event_type="pdf_summary_generated",
                description=f"PDF report ({lang}) generated for complaint: {complaint.reference_number}",
                request=request,
                content_object=complaint,
                metadata={"complaint_id": str(pk), "lang": lang},
            )

            return response

        except ImportError:
            return Response({"error": "WeasyPrint is not installed"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
        except Exception as e:
            logger.error(f"Error generating PDF summary for complaint {pk}: {e}")
            return Response({"error": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    @action(detail=True, methods=["post"])
    def save_resolution(self, request, pk=None):
        """
        Save final resolution for the complaint.

        Allows user to save an edited or directly generated resolution.
        Optionally updates complaint status to RESOLVED.
        """
        complaint = self.get_object()

        # Check permission
        if not (request.user.is_px_admin() or request.user.is_hospital_admin()):
            return Response(
                {"error": "Only PX Admins or Hospital Admins can save resolutions"}, status=status.HTTP_403_FORBIDDEN
            )

        resolution_text = request.data.get("resolution")
        mark_resolved = request.data.get("mark_resolved", False)

        if not resolution_text:
            return Response({"error": "Resolution text is required"}, status=status.HTTP_400_BAD_REQUEST)

        # Save resolution
        complaint.resolution = resolution_text
        complaint.resolution_category = ComplaintResolutionCategory.FULL_ACTION_TAKEN

        if mark_resolved:
            complaint.status = ComplaintStatus.RESOLVED
            complaint.resolved_at = timezone.now()
            complaint.resolved_by = request.user

        complaint.save()

        # Create update
        ComplaintUpdate.objects.create(
            complaint=complaint,
            update_type="resolution",
            message=f"Resolution added{' and complaint marked as resolved' if mark_resolved else ''}",
            created_by=request.user,
            metadata={
                "resolution_category": ComplaintResolutionCategory.FULL_ACTION_TAKEN,
                "mark_resolved": mark_resolved,
            },
        )

        # Log audit
        AuditService.log_from_request(
            event_type="resolution_saved",
            description=f"Resolution saved{' and complaint resolved' if mark_resolved else ''}",
            request=request,
            content_object=complaint,
            metadata={"mark_resolved": mark_resolved},
        )

        return Response(
            {
                "success": True,
                "message": f"Resolution saved successfully{' and complaint marked as resolved' if mark_resolved else ''}",
                "complaint_id": str(complaint.id),
                "status": complaint.status,
            }
        )

    @action(detail=True, methods=["post"])
    def convert_to_appreciation(self, request, pk=None):
        """
        Convert complaint to appreciation.

        Creates an Appreciation record from a complaint marked as 'appreciation' type.
        Maps complaint data to appreciation fields and links both records.
        Optionally closes the complaint after conversion.
        """
        complaint = self.get_object()

        # Check if complaint is in active status
        if not complaint.is_active_status:
            return Response(
                {
                    "error": f"Cannot convert complaint with status '{complaint.get_status_display()}'. Complaint must be Open, In Progress, or Partially Resolved."
                },
                status=status.HTTP_400_BAD_REQUEST,
            )

        # Check if complaint is appreciation type
        if complaint.complaint_type != "appreciation":
            return Response(
                {"error": "Only appreciation-type complaints can be converted to appreciations"},
                status=status.HTTP_400_BAD_REQUEST,
            )

        # Check if already converted
        if complaint.metadata.get("appreciation_id"):
            return Response(
                {"error": "This complaint has already been converted to an appreciation"},
                status=status.HTTP_400_BAD_REQUEST,
            )

        # Get form data
        recipient_type = request.data.get("recipient_type", "user")  # 'user' or 'physician'
        recipient_id = request.data.get("recipient_id")
        category_id = request.data.get("category_id")
        message_en = request.data.get("message_en", complaint.description)
        message_ar = request.data.get("message_ar", complaint.short_description_ar or "")
        visibility = request.data.get("visibility", "private")
        is_anonymous = request.data.get("is_anonymous", True)
        close_complaint = request.data.get("close_complaint", False)

        # Validate recipient
        from django.contrib.contenttypes.models import ContentType

        if recipient_type == "user":
            from apps.accounts.models import User

            try:
                recipient_user = User.objects.get(id=recipient_id)
                recipient_content_type = ContentType.objects.get_for_model(User)
                recipient_object_id = recipient_user.id
            except User.DoesNotExist:
                return Response({"error": "Recipient user not found"}, status=status.HTTP_404_NOT_FOUND)
        elif recipient_type == "physician":
            from apps.physicians.models import Physician

            try:
                recipient_physician = Physician.objects.get(id=recipient_id)
                recipient_content_type = ContentType.objects.get_for_model(Physician)
                recipient_object_id = recipient_physician.id
            except Physician.DoesNotExist:
                return Response({"error": "Recipient physician not found"}, status=status.HTTP_404_NOT_FOUND)
        else:
            return Response(
                {"error": 'Invalid recipient_type. Must be "user" or "physician"'}, status=status.HTTP_400_BAD_REQUEST
            )

        # Validate category
        from apps.appreciation.models import AppreciationCategory

        try:
            category = AppreciationCategory.objects.get(id=category_id)
        except AppreciationCategory.DoesNotExist:
            return Response({"error": "Appreciation category not found"}, status=status.HTTP_404_NOT_FOUND)

        # Determine sender (patient or anonymous)
        sender = None
        if not is_anonymous and complaint.patient and complaint.patient.user:
            sender = complaint.patient.user

        # Create Appreciation
        from apps.appreciation.models import Appreciation

        appreciation = Appreciation.objects.create(
            sender=sender,
            recipient_content_type=recipient_content_type,
            recipient_object_id=recipient_object_id,
            hospital=complaint.hospital,
            department=complaint.department,
            category=category,
            message_en=message_en,
            message_ar=message_ar,
            visibility=visibility,
            status=Appreciation.AppreciationStatus.DRAFT,
            is_anonymous=is_anonymous,
            metadata={
                "source_complaint_id": str(complaint.id),
                "source_complaint_title": complaint.title,
                "converted_from_complaint": True,
                "converted_by": str(request.user.id),
                "converted_at": timezone.now().isoformat(),
            },
        )

        # Send appreciation (triggers notification)
        appreciation.send()

        # Link appreciation to complaint
        if not complaint.metadata:
            complaint.metadata = {}
        complaint.metadata["appreciation_id"] = str(appreciation.id)
        complaint.metadata["converted_to_appreciation"] = True
        complaint.metadata["converted_to_appreciation_at"] = timezone.now().isoformat()
        complaint.metadata["converted_by"] = str(request.user.id)
        complaint.save(update_fields=["metadata"])

        # Close complaint if requested
        complaint_closed = False
        if close_complaint:
            complaint.status = "closed"
            complaint.closed_at = timezone.now()
            complaint.closed_by = request.user
            complaint.save(update_fields=["status", "closed_at", "closed_by"])
            complaint_closed = True

            # Create status update
            ComplaintUpdate.objects.create(
                complaint=complaint,
                update_type="status_change",
                message="Complaint closed after converting to appreciation",
                created_by=request.user,
                old_status="open",
                new_status="closed",
            )

        # Create conversion update
        ComplaintUpdate.objects.create(
            complaint=complaint,
            update_type="note",
            message=f"Converted to appreciation (Appreciation #{appreciation.id})",
            created_by=request.user,
            metadata={
                "appreciation_id": str(appreciation.id),
                "converted_from_complaint": True,
                "close_complaint": close_complaint,
            },
        )

        # Log audit
        AuditService.log_from_request(
            event_type="complaint_converted_to_appreciation",
            description=f"Complaint converted to appreciation: {appreciation.message_en[:100]}",
            request=request,
            content_object=complaint,
            metadata={
                "appreciation_id": str(appreciation.id),
                "close_complaint": close_complaint,
                "is_anonymous": is_anonymous,
            },
        )

        # Build appreciation URL
        from django.contrib.sites.shortcuts import get_current_site

        site = get_current_site(request)
        appreciation_url = f"https://{site.domain}/appreciations/{appreciation.id}/"

        return Response(
            {
                "success": True,
                "message": "Complaint successfully converted to appreciation",
                "appreciation_id": str(appreciation.id),
                "appreciation_url": appreciation_url,
                "complaint_closed": complaint_closed,
            },
            status=status.HTTP_201_CREATED,
        )

    @action(detail=True, methods=["post"])
    def send_resolution_notification(self, request, pk=None):
        """
        Send resolution notification to patient.

        Sends email notification to patient with resolution details.
        Optionally sends SMS if phone number is available.
        Creates ComplaintUpdate entry and logs audit trail.
        """
        complaint = self.get_object()

        # Check if complaint is resolved
        if complaint.status != "resolved":
            return Response(
                {"error": "Can only send resolution notification for resolved complaints"},
                status=status.HTTP_400_BAD_REQUEST,
            )

        # Check if resolution exists
        if not complaint.resolution:
            return Response(
                {"error": "Complaint must have resolution details before sending notification"},
                status=status.HTTP_400_BAD_REQUEST,
            )

        # Determine recipient (patient or contact)
        recipient_email = None
        recipient_phone = None
        recipient_name = None

        # Try patient first
        if complaint.patient:
            if complaint.patient.email:
                recipient_email = complaint.patient.email
            if complaint.patient.phone:
                recipient_phone = complaint.patient.phone
            recipient_name = complaint.patient.get_full_name()

        # Fall back to contact info
        if not recipient_email:
            recipient_email = complaint.contact_email
        if not recipient_name:
            recipient_name = complaint.contact_name
        if not recipient_phone:
            recipient_phone = complaint.contact_phone

        # Validate at least email is available
        if not recipient_email:
            return Response(
                {"error": "No email address found for patient or contact"}, status=status.HTTP_400_BAD_REQUEST
            )

        # Build email subject and body
        subject = f"Complaint Resolution - #{complaint.id}"

        # Build email body
        email_body = f"""
Dear {recipient_name},

We are pleased to inform you that your complaint has been resolved.

COMPLAINT DETAILS:
----------------
Reference: #{complaint.id}
Title: {complaint.title}
Status: {complaint.get_status_display()}

RESOLUTION:
-----------
Category: {complaint.get_resolution_category_display()}

{complaint.resolution}

"""

        # Add additional context if available
        if complaint.resolved_by:
            email_body += f"""
Resolved by: {complaint.resolved_by.get_full_name()}
Resolved at: {complaint.resolved_at.strftime("%Y-%m-%d %H:%M")}
"""

        email_body += f"""

If you have any further questions or concerns about this resolution, 
please don't hesitate to contact us.

Thank you for your patience and for giving us the opportunity to address your concerns.

---
This is an automated message from PX360 Complaint Management System.
"""

        # Send email using NotificationService
        from apps.notifications.services import NotificationService, get_email_header_html

        try:
            notification_log = NotificationService.send_email(
                email=recipient_email,
                subject=subject,
                message=email_body,
                html_message=f"""
<div style="font-family: 'Segoe UI', Tahoma, sans-serif; max-width: 600px; margin: 0 auto; border: 1px solid #e5e7eb; border-radius: 8px; overflow: hidden;">
    {get_email_header_html()}
    <div style="padding: 20px;">
        <h2 style="color: #005696; font-size: 18px; margin: 0 0 12px 0;">Complaint Resolution</h2>
        <p style="margin: 0 0 12px 0;">Dear {recipient_name},</p>
        <p style="margin: 0 0 12px 0;">We are pleased to inform you that your complaint has been resolved.</p>
        <table style="width: 100%; border-collapse: collapse; margin: 0 0 12px 0;">
            <tr><td style="padding: 4px 0; color: #6b7280; width: 120px;">Reference:</td><td style="padding: 4px 0;"><strong>#{complaint.id}</strong></td></tr>
            <tr><td style="padding: 4px 0; color: #6b7280;">Title:</td><td style="padding: 4px 0;">{complaint.title}</td></tr>
            <tr><td style="padding: 4px 0; color: #6b7280;">Category:</td><td style="padding: 4px 0;">{complaint.get_resolution_category_display()}</td></tr>
        </table>
        <div style="background: #f9fafb; padding: 12px; border-radius: 6px; margin: 0 0 12px 0;">
            <p style="margin: 0;">{complaint.resolution}</p>
        </div>
        <p style="margin: 0 0 12px 0; color: #6b7280;">If you have any further questions or concerns, please don't hesitate to contact us.</p>
        <p style="margin: 0; color: #6b7280;">Thank you for your patience and for giving us the opportunity to address your concerns.</p>
    </div>
</div>
""",
                related_object=complaint,
                metadata={
                    "notification_type": "resolution_notification",
                    "recipient_name": recipient_name,
                    "recipient_phone": recipient_phone,
                    "sender_id": str(request.user.id),
                    "resolution_category": complaint.resolution_category,
                },
            )
        except Exception as e:
            return Response({"error": f"Failed to send email: {str(e)}"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

        # Optionally send SMS if phone is available
        sms_sent = False
        if recipient_phone:
            try:
                # Build SMS message (shorter)
                sms_message = f"PX360: Your complaint #{complaint.id} has been resolved. Resolution Category: {complaint.get_resolution_category_display()}. Check your email for details."

                # Send SMS (if SMS service is configured)
                # This is a placeholder - actual SMS sending depends on your SMS provider
                sms_sent = True  # Set to True if SMS is actually sent

                if sms_sent:
                    # Log SMS in metadata
                    complaint.metadata["resolution_sms_sent_at"] = timezone.now().isoformat()
                    complaint.metadata["resolution_sms_sent_to"] = recipient_phone
                    complaint.save(update_fields=["metadata"])
            except Exception as e:
                # Log error but don't fail the operation
                import logging

                logger = logging.getLogger(__name__)
                logger.error(f"Failed to send SMS: {e}")

        # Create ComplaintUpdate entry
        ComplaintUpdate.objects.create(
            complaint=complaint,
            update_type="communication",
            message=f"Resolution notification sent to {recipient_name}",
            created_by=request.user,
            metadata={
                "notification_type": "resolution_notification",
                "recipient_name": recipient_name,
                "recipient_email": recipient_email,
                "notification_log_id": str(notification_log.id) if notification_log else None,
                "sms_sent": sms_sent,
            },
        )

        # Log audit
        AuditService.log_from_request(
            event_type="resolution_notification_sent",
            description=f"Resolution notification sent to {recipient_name}",
            request=request,
            content_object=complaint,
            metadata={
                "recipient_name": recipient_name,
                "recipient_email": recipient_email,
                "recipient_phone": recipient_phone,
                "sms_sent": sms_sent,
                "resolution_category": complaint.resolution_category,
            },
        )

        return Response(
            {
                "success": True,
                "message": "Resolution notification sent successfully",
                "recipient": recipient_name,
                "recipient_email": recipient_email,
                "sms_sent": sms_sent,
            }
        )

    @action(detail=True, methods=["post"])
    def update_taxonomy(self, request, pk=None):
        """
        Update the 4-level SHCT taxonomy classification for a complaint.

        Allows PX Admins and Hospital Admins to manually correct or update
        the AI-generated taxonomy classification.

        Required fields:
        - domain_id: UUID of the Level 1 Domain (ComplaintCategory)
        - category_id: UUID of the Level 2 Category (ComplaintCategory)
        - subcategory_id: UUID of the Level 3 Subcategory (ComplaintCategory)
        - classification_id: UUID of the Level 4 Classification (ComplaintCategory)

        Optional fields:
        - note: Optional note explaining the change
        """
        complaint = self.get_object()
        user = request.user

        # Check permissions
        if not (user.is_px_admin() or user.is_hospital_admin()):
            return Response(
                {"error": "Only PX Admins and Hospital Admins can update taxonomy"}, status=status.HTTP_403_FORBIDDEN
            )

        # Get taxonomy IDs from request
        domain_id = request.data.get("domain_id")
        category_id = request.data.get("category_id")
        subcategory_id = request.data.get("subcategory_id")
        classification_id = request.data.get("classification_id")
        note = request.data.get("note", "")

        # Validate that at least one field is provided
        if not any([domain_id, category_id, subcategory_id, classification_id]):
            return Response(
                {
                    "error": "At least one taxonomy level (domain_id, category_id, subcategory_id, or classification_id) must be provided"
                },
                status=status.HTTP_400_BAD_REQUEST,
            )

        from apps.complaints.models import ComplaintCategory

        changes = []
        errors = []

        # Store old values for logging
        old_domain = complaint.domain
        old_category = complaint.category
        old_subcategory_obj = complaint.subcategory_obj
        old_classification_obj = complaint.classification_obj

        try:
            # Level 1: Domain
            if domain_id:
                try:
                    domain = ComplaintCategory.objects.get(
                        id=domain_id, level=ComplaintCategory.LevelChoices.DOMAIN, is_active=True
                    )
                    complaint.domain = domain
                    changes.append(f"Domain: {old_domain.name_en if old_domain else 'None'} -> {domain.name_en}")
                except ComplaintCategory.DoesNotExist:
                    errors.append(f"Domain with ID {domain_id} not found or not active")

            # Level 2: Category (must be child of domain if domain is set)
            if category_id:
                try:
                    category_query = ComplaintCategory.objects.filter(
                        id=category_id, level=ComplaintCategory.LevelChoices.CATEGORY, is_active=True
                    )
                    # If domain is set, ensure category is child of domain
                    if complaint.domain:
                        category_query = category_query.filter(parent=complaint.domain)

                    category = category_query.first()
                    if category:
                        complaint.category = category
                        changes.append(
                            f"Category: {old_category.name_en if old_category else 'None'} -> {category.name_en}"
                        )
                    else:
                        errors.append(
                            f"Category with ID {category_id} not found, not active, or not under the selected domain"
                        )
                except Exception as e:
                    errors.append(f"Error setting category: {str(e)}")

            # Level 3: Subcategory (must be child of category if category is set)
            if subcategory_id:
                try:
                    subcategory_query = ComplaintCategory.objects.filter(
                        id=subcategory_id, level=ComplaintCategory.LevelChoices.SUBCATEGORY, is_active=True
                    )
                    # If category is set, ensure subcategory is child of category
                    if complaint.category:
                        subcategory_query = subcategory_query.filter(parent=complaint.category)

                    subcategory = subcategory_query.first()
                    if subcategory:
                        complaint.subcategory_obj = subcategory
                        complaint.subcategory = subcategory.code or subcategory.name_en
                        changes.append(
                            f"Subcategory: {old_subcategory_obj.name_en if old_subcategory_obj else 'None'} -> {subcategory.name_en}"
                        )
                    else:
                        errors.append(
                            f"Subcategory with ID {subcategory_id} not found, not active, or not under the selected category"
                        )
                except Exception as e:
                    errors.append(f"Error setting subcategory: {str(e)}")

            # Level 4: Classification (must be child of subcategory if subcategory is set)
            if classification_id:
                try:
                    classification_query = ComplaintCategory.objects.filter(
                        id=classification_id, level=ComplaintCategory.LevelChoices.CLASSIFICATION, is_active=True
                    )
                    # If subcategory_obj is set, ensure classification is child of subcategory
                    if complaint.subcategory_obj:
                        classification_query = classification_query.filter(parent=complaint.subcategory_obj)

                    classification = classification_query.first()
                    if classification:
                        complaint.classification_obj = classification
                        complaint.classification = classification.code or classification.name_en
                        changes.append(
                            f"Classification: {old_classification_obj.name_en if old_classification_obj else 'None'} -> {classification.name_en}"
                        )
                    else:
                        errors.append(
                            f"Classification with ID {classification_id} not found, not active, or not under the selected subcategory"
                        )
                except Exception as e:
                    errors.append(f"Error setting classification: {str(e)}")

            # If there were errors, return them without saving
            if errors:
                return Response(
                    {"error": "Some taxonomy levels could not be updated", "errors": errors, "changes_made": changes},
                    status=status.HTTP_400_BAD_REQUEST,
                )

            # Save the complaint
            complaint.save(
                update_fields=[
                    "domain",
                    "category",
                    "subcategory",
                    "subcategory_obj",
                    "classification",
                    "classification_obj",
                ]
            )

            # Create timeline entry
            change_message = "Taxonomy updated:\n" + "\n".join(changes)
            if note:
                change_message += f"\n\nNote: {note}"

            ComplaintUpdate.objects.create(
                complaint=complaint,
                update_type="note",
                message=change_message,
                created_by=user,
                metadata={"taxonomy_update": True, "changes": changes, "note": note, "updated_by": str(user.id)},
            )

            # Log audit
            AuditService.log_from_request(
                event_type="taxonomy_updated",
                description=f"Taxonomy updated for complaint: {complaint.title}",
                request=request,
                content_object=complaint,
                metadata={"changes": changes, "note": note, "updated_by": str(user.id)},
            )

            # Update metadata to reflect manual update
            if not complaint.metadata:
                complaint.metadata = {}
            if "ai_analysis" not in complaint.metadata:
                complaint.metadata["ai_analysis"] = {}
            complaint.metadata["ai_analysis"]["taxonomy_manually_updated"] = True
            complaint.metadata["ai_analysis"]["taxonomy_updated_by"] = str(user.id)
            complaint.metadata["ai_analysis"]["taxonomy_updated_at"] = timezone.now().isoformat()
            complaint.save(update_fields=["metadata"])

            return Response(
                {
                    "success": True,
                    "message": "Taxonomy updated successfully",
                    "changes": changes,
                    "taxonomy": {
                        "domain": {
                            "id": str(complaint.domain.id) if complaint.domain else None,
                            "name_en": complaint.domain.name_en if complaint.domain else None,
                            "name_ar": complaint.domain.name_ar if complaint.domain else None,
                        },
                        "category": {
                            "id": str(complaint.category.id) if complaint.category else None,
                            "name_en": complaint.category.name_en if complaint.category else None,
                            "name_ar": complaint.category.name_ar if complaint.category else None,
                        },
                        "subcategory": {
                            "id": str(complaint.subcategory_obj.id) if complaint.subcategory_obj else None,
                            "name_en": complaint.subcategory_obj.name_en if complaint.subcategory_obj else None,
                            "name_ar": complaint.subcategory_obj.name_ar if complaint.subcategory_obj else None,
                            "code": complaint.subcategory,
                        },
                        "classification": {
                            "id": str(complaint.classification_obj.id) if complaint.classification_obj else None,
                            "name_en": complaint.classification_obj.name_en if complaint.classification_obj else None,
                            "name_ar": complaint.classification_obj.name_ar if complaint.classification_obj else None,
                            "code": complaint.classification,
                        },
                    },
                }
            )

        except Exception as e:
            logger.error(f"Error updating taxonomy: {str(e)}")
            return Response(
                {"error": f"Failed to update taxonomy: {str(e)}"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )

    @action(detail=True, methods=["get"])
    def taxonomy_options(self, request, pk=None):
        """
        Get available taxonomy options for the complaint's hierarchy.

        Returns the full SHCT taxonomy hierarchy for building cascading dropdowns.
        Includes only active categories.
        """
        complaint = self.get_object()

        from apps.complaints.models import ComplaintCategory
        from django.db.models import Prefetch

        # Build the hierarchy
        domains = ComplaintCategory.objects.filter(
            level=ComplaintCategory.LevelChoices.DOMAIN, is_active=True
        ).order_by("order", "name_en")

        result = []
        for domain in domains:
            domain_data = {
                "id": str(domain.id),
                "code": domain.code or domain.name_en.upper(),
                "name_en": domain.name_en,
                "name_ar": domain.name_ar,
                "is_selected": complaint.domain and complaint.domain.id == domain.id,
                "categories": [],
            }

            # Get categories for this domain
            categories = ComplaintCategory.objects.filter(
                parent=domain, level=ComplaintCategory.LevelChoices.CATEGORY, is_active=True
            ).order_by("order", "name_en")

            for category in categories:
                category_data = {
                    "id": str(category.id),
                    "code": category.code or category.name_en.upper(),
                    "name_en": category.name_en,
                    "name_ar": category.name_ar,
                    "is_selected": complaint.category and complaint.category.id == category.id,
                    "subcategories": [],
                }

                # Get subcategories for this category
                subcategories = ComplaintCategory.objects.filter(
                    parent=category, level=ComplaintCategory.LevelChoices.SUBCATEGORY, is_active=True
                ).order_by("order", "name_en")

                for subcategory in subcategories:
                    subcategory_data = {
                        "id": str(subcategory.id),
                        "code": subcategory.code or subcategory.name_en.upper(),
                        "name_en": subcategory.name_en,
                        "name_ar": subcategory.name_ar,
                        "is_selected": complaint.subcategory_obj and complaint.subcategory_obj.id == subcategory.id,
                        "classifications": [],
                    }

                    # Get classifications for this subcategory
                    classifications = ComplaintCategory.objects.filter(
                        parent=subcategory, level=ComplaintCategory.LevelChoices.CLASSIFICATION, is_active=True
                    ).order_by("order", "name_en")

                    for classification in classifications:
                        classification_data = {
                            "id": str(classification.id),
                            "code": classification.code,
                            "name_en": classification.name_en,
                            "name_ar": classification.name_ar,
                            "is_selected": complaint.classification_obj
                            and complaint.classification_obj.id == classification.id,
                        }
                        subcategory_data["classifications"].append(classification_data)

                    category_data["subcategories"].append(subcategory_data)

                domain_data["categories"].append(category_data)

            result.append(domain_data)

        return Response(
            {
                "success": True,
                "hierarchy": result,
                "current": {
                    "domain_id": str(complaint.domain.id) if complaint.domain else None,
                    "category_id": str(complaint.category.id) if complaint.category else None,
                    "subcategory_id": str(complaint.subcategory_obj.id) if complaint.subcategory_obj else None,
                    "classification_id": str(complaint.classification_obj.id) if complaint.classification_obj else None,
                },
            }
        )

    @action(detail=True, methods=["post"])
    def reanalyze_ai(self, request, pk=None):
        """Trigger re-analysis of a complaint with AI (synchronous - waits for result)"""
        complaint = self.get_object()

        user = request.user
        can_reanalyze = user.is_px_admin() or (user.is_hospital_admin() and user.hospital == complaint.hospital)

        if not can_reanalyze:
            return Response(
                {"error": "You do not have permission to re-analyze this complaint"},
                status=status.HTTP_403_FORBIDDEN,
            )

        try:
            from apps.core.ai_service import AIService
            from apps.complaints.tasks import _apply_complaint_ai_analysis
            from apps.complaints.models import ComplaintUpdate

            category_name = None
            if complaint.category:
                category_name = complaint.category.name_en

            analysis = AIService.analyze_complaint(
                title=complaint.title,
                description=complaint.description,
                category=category_name,
                hospital_id=complaint.hospital.id,
            )

            emotion_analysis = AIService.analyze_emotion(text=complaint.description)

            result = _apply_complaint_ai_analysis(complaint, analysis, emotion_analysis)

            ComplaintUpdate.objects.create(
                complaint=complaint,
                update_type="note",
                message="AI re-analysis complete.",
                created_by=request.user,
            )

            AuditService.log_from_request(
                event_type="complaint_reanalyzed",
                description=f"Complaint {complaint.reference_number} re-analyzed with AI",
                request=request,
                content_object=complaint,
            )

            emotion_map = {
                "anger": "Anger",
                "sadness": "Sadness",
                "confusion": "Confusion",
                "fear": "Fear",
                "neutral": "Neutral",
            }
            badge_map = {
                "anger": "danger",
                "sadness": "primary",
                "confusion": "warning",
                "fear": "info",
                "neutral": "secondary",
            }

            return Response(
                {
                    "success": True,
                    "severity": result.get("severity", ""),
                    "severity_display": complaint.get_severity_display(),
                    "priority": result.get("priority", ""),
                    "priority_display": complaint.get_priority_display(),
                    "emotion": result.get("emotion", "neutral"),
                    "emotion_display": emotion_map.get(result.get("emotion", "neutral"), "Neutral"),
                    "emotion_badge_class": badge_map.get(result.get("emotion", "neutral"), "secondary"),
                    "emotion_intensity": result.get("emotion_intensity", 0.0),
                    "emotion_intensity_percent": result.get("emotion_intensity", 0.0) * 100,
                    "emotion_confidence": result.get("emotion_confidence", 0.0),
                    "emotion_confidence_percent": result.get("emotion_confidence", 0.0) * 100,
                    "short_description_en": result.get("short_description_en", ""),
                    "short_description_ar": result.get("short_description_ar", ""),
                    "suggested_actions": result.get("suggested_actions", []),
                    "suggested_action_en": result.get("suggested_action_en", ""),
                    "suggested_action_ar": result.get("suggested_action_ar", ""),
                }
            )

        except Exception as e:
            logger.error(f"AI re-analysis failed for complaint {pk}: {e}")
            return Response(
                {"success": False, "error": f"AI analysis failed: {str(e)}"},
                status=status.HTTP_500_INTERNAL_SERVER_ERROR,
            )


class ComplaintAttachmentViewSet(viewsets.ModelViewSet):
    """ViewSet for Complaint Attachments"""

    queryset = ComplaintAttachment.objects.all()
    serializer_class = ComplaintAttachmentSerializer
    permission_classes = [IsAuthenticated]
    filterset_fields = ["complaint"]
    ordering = ["-created_at"]

    def get_queryset(self):
        queryset = super().get_queryset().select_related("complaint", "uploaded_by")
        user = self.request.user

        # Filter based on complaint access
        if user.is_px_admin():
            return queryset

        if user.is_hospital_admin() and user.hospital:
            return queryset.filter(complaint__hospital=user.hospital)

        if user.hospital:
            return queryset.filter(complaint__hospital=user.hospital)

        return queryset.none()


class InquiryViewSet(viewsets.ModelViewSet):
    """ViewSet for Inquiries"""

    queryset = Inquiry.objects.all()
    serializer_class = InquirySerializer
    permission_classes = [IsAuthenticated]
    filterset_fields = [
        "status",
        "category",
        "source",
        "hospital",
        "department",
        "assigned_to",
        "hospital__organization",
    ]
    search_fields = ["subject", "message", "contact_name", "patient__mrn"]
    ordering_fields = ["created_at"]
    ordering = ["-created_at"]

    def perform_create(self, serializer):
        """Auto-set created_by from request.user and trigger AI analysis in background"""
        inquiry = serializer.save(created_by=self.request.user)

        from apps.complaints.tasks import analyze_inquiry_with_ai, notify_staff_new_item

        analyze_inquiry_with_ai.delay(str(inquiry.id))
        notify_staff_new_item.delay("inquiry", str(inquiry.id))

        AuditService.log_from_request(
            event_type="inquiry_created",
            description=f"Inquiry created: {inquiry.subject}",
            request=self.request,
            content_object=inquiry,
            metadata={"created_by": str(inquiry.created_by.id) if inquiry.created_by else None},
        )

    def get_queryset(self):
        """Filter inquiries based on user role"""
        queryset = (
            super()
            .get_queryset()
            .select_related("patient", "hospital", "department", "assigned_to", "responded_by", "created_by")
        )

        user = self.request.user

        # PX Admins see all inquiries
        if user.is_px_admin():
            return queryset

        # Source Users see ONLY inquiries THEY created
        if hasattr(user, "source_user_profile") and user.source_user_profile.exists():
            return queryset.filter(created_by=user)

        # Patients see ONLY their own inquiries (if they have user accounts)
        if hasattr(user, "patient_profile"):
            return queryset.filter(patient__user=user)

        # Hospital Admins see inquiries for their hospital
        if user.is_hospital_admin() and user.hospital:
            return queryset.filter(hospital=user.hospital)

        # Department Managers see inquiries for their department
        if user.is_department_manager() and user.department:
            return queryset.filter(department=user.department)

        # Others see inquiries for their hospital
        if user.hospital:
            return queryset.filter(hospital=user.hospital)

        return queryset.none()

    @action(detail=True, methods=["post"])
    def respond(self, request, pk=None):
        """Respond to inquiry"""
        inquiry = self.get_object()
        response_text = request.data.get("response")

        if not response_text:
            return Response({"error": "response is required"}, status=status.HTTP_400_BAD_REQUEST)

        inquiry.response = response_text
        inquiry.responded_at = timezone.now()
        inquiry.responded_by = request.user
        inquiry.status = "resolved"
        inquiry.save()

        return Response({"message": "Response submitted successfully"})

    @action(detail=True, methods=["post"])
    def generate_ai_response(self, request, pk=None):
        """
        Generate AI-powered response for an inquiry in both English and Arabic.

        Admin can edit the generated response before sending to the inquirer.
        """
        inquiry = self.get_object()

        user = request.user
        can_generate = (
            user.is_px_admin()
            or (user.is_hospital_admin() and user.hospital == inquiry.hospital)
            or inquiry.assigned_to == user
        )

        if not can_generate:
            return Response(
                {"error": "You do not have permission to generate AI response for this inquiry"},
                status=status.HTTP_403_FORBIDDEN,
            )

        try:
            from apps.core.ai_service import AIService

            ai_description_en = ""
            ai_description_ar = ""
            if inquiry.metadata and "ai_analysis" in inquiry.metadata:
                ai_description_en = inquiry.metadata["ai_analysis"].get("short_description_en", "")
                ai_description_ar = inquiry.metadata["ai_analysis"].get("short_description_ar", "")

            category_display = inquiry.get_category_display()
            hospital_name = inquiry.hospital.name if inquiry.hospital else "Unknown"

            dept_response_section = ""
            if inquiry.department_response_en or inquiry.department_response_ar:
                dept_response_en = inquiry.department_response_en or ""
                dept_response_ar = inquiry.department_response_ar or ""
                dept_summary_en = inquiry.department_response_summary_en or ""
                dept_summary_ar = inquiry.department_response_summary_ar or ""
                dept_response_section = f"""
DEPARTMENT/STAFF RESPONSE (use this as the primary basis for your answer):
- English: {dept_summary_en or dept_response_en}
- Arabic: {dept_summary_ar or dept_response_ar}

IMPORTANT: The department has already provided a technical response above. Your task is to transform it into a clear, patient-friendly response. Keep the factual information and actions taken, but rephrase in simple, empathetic language a patient would understand. Do NOT omit any important details from the department response."""

            prompt = f"""As a healthcare inquiry response specialist, generate a professional response to this inquiry in BOTH English and Arabic.

INQUIRY DETAILS:
- Subject: {inquiry.subject}
- Message: {inquiry.message}
- Category: {category_display}
- Hospital: {hospital_name}
- Inquirer Name: {inquiry.contact_name or "Unknown"}

AI SUMMARY (for context):
- English: {ai_description_en}
- Arabic: {ai_description_ar}
{dept_response_section}

Based on the above information, generate a professional response that:
1. Acknowledges the inquiry and thanks the inquirer
2. Directly addresses the question/request
3. Provides helpful, accurate information
4. Offers further assistance if needed
5. Uses a professional, empathetic tone

IMPORTANT: Provide the response in BOTH languages as JSON:
{{
    "response_en": "The response text in English (2-4 paragraphs)",
    "response_ar": "نص الرد بالعربية (2-4 فقرات)"
}}

Ensure both versions convey the same meaning and are professionally written for healthcare settings."""

            system_prompt = """You are an expert healthcare inquiry response specialist fluent in both English and Arabic.
Your task is to generate comprehensive, professional responses to patient inquiries in both languages.
Be helpful, accurate, and empathetic. Use professional tone appropriate for healthcare.
Always provide valid JSON output with both response_en and response_ar fields.
Use Modern Standard Arabic (Fusha) - الفصحى."""

            ai_response = AIService.chat_completion(
                prompt=prompt,
                system_prompt=system_prompt,
                temperature=0.4,
                max_tokens=1500,
                response_format="json_object",
            )

            import json

            response_data = json.loads(ai_response)
            response_en = response_data.get("response_en", "").strip()
            response_ar = response_data.get("response_ar", "").strip()

            AuditService.log_from_request(
                event_type="ai_inquiry_response_generated",
                description=f"AI response generated for inquiry {inquiry.reference_number}",
                request=request,
                content_object=inquiry,
                metadata={
                    "inquiry_id": str(inquiry.id),
                    "generated_response_en_length": len(response_en),
                    "generated_response_ar_length": len(response_ar),
                },
            )

            return Response(
                {
                    "success": True,
                    "response_en": response_en,
                    "response_ar": response_ar,
                }
            )

        except Exception as e:
            logger.error(f"AI inquiry response generation failed: {e}")
            return Response(
                {"success": False, "error": f"Failed to generate response: {str(e)}"},
                status=status.HTTP_500_INTERNAL_SERVER_ERROR,
            )

    @action(detail=True, methods=["post"])
    def reanalyze_ai(self, request, pk=None):
        """Trigger re-analysis of an inquiry with AI (synchronous - waits for result)"""
        inquiry = self.get_object()

        user = request.user
        can_reanalyze = (
            user.is_px_admin()
            or (user.is_hospital_admin() and user.hospital == inquiry.hospital)
            or inquiry.assigned_to == user
        )

        if not can_reanalyze:
            return Response(
                {"error": "You do not have permission to re-analyze this inquiry"},
                status=status.HTTP_403_FORBIDDEN,
            )

        try:
            from apps.core.ai_service import AIService, AIServiceError
            from apps.complaints.tasks import _apply_inquiry_ai_analysis
            from apps.complaints.models import InquiryUpdate

            analysis = AIService.analyze_inquiry(
                subject=inquiry.subject,
                message=inquiry.message,
                category=inquiry.get_category_display(),
                hospital_id=inquiry.hospital.id,
            )

            emotion_analysis = AIService.analyze_emotion(text=inquiry.message)

            _apply_inquiry_ai_analysis(inquiry, analysis, emotion_analysis)

            InquiryUpdate.objects.create(
                inquiry=inquiry,
                update_type="note",
                message="AI re-analysis complete.",
                created_by=request.user,
            )

            AuditService.log_from_request(
                event_type="inquiry_reanalyzed",
                description=f"Inquiry {inquiry.reference_number} re-analyzed with AI",
                request=request,
                content_object=inquiry,
            )

            return Response(
                {
                    "success": True,
                    "priority": inquiry.priority,
                    "priority_display": inquiry.get_priority_display(),
                    "emotion": emotion_analysis.get("emotion", "neutral"),
                    "emotion_display": {
                        "anger": "Anger",
                        "sadness": "Sadness",
                        "confusion": "Confusion",
                        "fear": "Fear",
                        "neutral": "Neutral",
                    }.get(emotion_analysis.get("emotion", "neutral"), "Neutral"),
                    "emotion_badge_class": {
                        "anger": "danger",
                        "sadness": "primary",
                        "confusion": "warning",
                        "fear": "info",
                        "neutral": "secondary",
                    }.get(emotion_analysis.get("emotion", "neutral"), "secondary"),
                    "emotion_intensity": emotion_analysis.get("intensity", 0.0),
                    "emotion_intensity_percent": emotion_analysis.get("intensity", 0.0) * 100,
                    "emotion_confidence": emotion_analysis.get("confidence", 0.0),
                    "emotion_confidence_percent": emotion_analysis.get("confidence", 0.0) * 100,
                    "short_description_en": analysis.get("short_description_en", ""),
                    "short_description_ar": analysis.get("short_description_ar", ""),
                }
            )

        except Exception as e:
            logger.error(f"AI re-analysis failed for inquiry {pk}: {e}")
            return Response(
                {"success": False, "error": f"AI analysis failed: {str(e)}"},
                status=status.HTTP_500_INTERNAL_SERVER_ERROR,
            )


class ComplaintPRInteractionViewSet(viewsets.ModelViewSet):
    """ViewSet for PR Interactions"""

    queryset = ComplaintPRInteraction.objects.all()
    serializer_class = ComplaintPRInteractionSerializer
    permission_classes = [IsAuthenticated]
    filterset_fields = ["complaint", "contact_method", "procedure_explained", "pr_staff"]
    ordering = ["-contact_date"]

    def get_queryset(self):
        queryset = super().get_queryset().select_related("complaint", "pr_staff", "created_by")
        user = self.request.user

        # Filter based on complaint access
        if user.is_px_admin():
            return queryset

        if user.is_hospital_admin() and user.hospital:
            return queryset.filter(complaint__hospital=user.hospital)

        if user.hospital:
            return queryset.filter(complaint__hospital=user.hospital)

        return queryset.none()

    def perform_create(self, serializer):
        """Auto-set created_by from request.user"""
        interaction = serializer.save(created_by=self.request.user)

        # Create complaint update
        ComplaintUpdate.objects.create(
            complaint=interaction.complaint,
            update_type="note",
            message=f"PR Interaction recorded: Contact via {interaction.get_contact_method_display()}",
            created_by=self.request.user,
            metadata={
                "interaction_id": str(interaction.id),
                "contact_method": interaction.contact_method,
                "procedure_explained": interaction.procedure_explained,
            },
        )

        AuditService.log_from_request(
            event_type="pr_interaction_created",
            description=f"PR Interaction recorded for complaint: {interaction.complaint.title}",
            request=self.request,
            content_object=interaction,
            metadata={"complaint_id": str(interaction.complaint.id), "contact_method": interaction.contact_method},
        )


class ComplaintMeetingViewSet(viewsets.ModelViewSet):
    """ViewSet for Complaint Meetings"""

    queryset = ComplaintMeeting.objects.all()
    serializer_class = ComplaintMeetingSerializer
    permission_classes = [IsAuthenticated]
    filterset_fields = ["complaint", "meeting_type"]
    ordering = ["-meeting_date"]

    def get_queryset(self):
        queryset = super().get_queryset().select_related("complaint", "created_by")
        user = self.request.user

        # Filter based on complaint access
        if user.is_px_admin():
            return queryset

        if user.is_hospital_admin() and user.hospital:
            return queryset.filter(complaint__hospital=user.hospital)

        if user.hospital:
            return queryset.filter(complaint__hospital=user.hospital)

        return queryset.none()

    def perform_create(self, serializer):
        """Auto-set created_by from request.user"""
        meeting = serializer.save(created_by=self.request.user)

        # Create complaint update
        ComplaintUpdate.objects.create(
            complaint=meeting.complaint,
            update_type="note",
            message=f"Meeting recorded: {meeting.get_meeting_type_display()} - {meeting.outcome[:100] if meeting.outcome else ''}",
            created_by=self.request.user,
            metadata={"meeting_id": str(meeting.id), "meeting_type": meeting.meeting_type},
        )

        # If outcome is provided, consider it as resolution
        if meeting.outcome and meeting.complaint.status not in ["resolved", "closed"]:
            meeting.complaint.status = "resolved"
            meeting.complaint.resolution = meeting.outcome
            meeting.complaint.resolved_at = timezone.now()
            meeting.complaint.resolved_by = self.request.user
            meeting.complaint.save(update_fields=["status", "resolution", "resolved_at", "resolved_by"])

            # Create status update
            ComplaintUpdate.objects.create(
                complaint=meeting.complaint,
                update_type="status_change",
                message=f"Complaint resolved through meeting",
                created_by=self.request.user,
                old_status="in_progress",
                new_status="resolved",
            )

        AuditService.log_from_request(
            event_type="meeting_created",
            description=f"Complaint Meeting recorded for: {meeting.complaint.title}",
            request=self.request,
            content_object=meeting,
            metadata={"complaint_id": str(meeting.complaint.id), "meeting_type": meeting.meeting_type},
        )


# Public views (no authentication required)
from django.shortcuts import render, redirect, get_object_or_404
from django.http import JsonResponse
from django.views.decorators.http import require_GET
from django.views.decorators.csrf import csrf_exempt


def api_locations(request):
    """
    API endpoint to get all locations for complaint form.

    Returns JSON list of all locations ordered by English name.
    Public endpoint (no authentication required).
    """
    from apps.organizations.models import LegacyLocation

    locations = LegacyLocation.objects.all().order_by("name_en")

    locations_list = [
        {
            "id": loc.id,
            "name": str(loc),  # Uses __str__ which prefers English name
        }
        for loc in locations
    ]

    return JsonResponse({"success": True, "locations": locations_list, "count": len(locations_list)})


@require_GET
def api_sections(request, location_id):
    """
    API endpoint to get sections for a specific location.

    Returns JSON list of main sections that have subsections
    for given location.
    Public endpoint (no authentication required).
    """
    from apps.organizations.models import LegacyMainSection, LegacySubSection

    # Get available sections that have subsections for this location
    available_section_ids = (
        LegacySubSection.objects.filter(location_id=location_id).values_list("main_section_id", flat=True).distinct()
    )

    sections = LegacyMainSection.objects.filter(id__in=available_section_ids).order_by("name_en")

    sections_list = [
        {
            "id": section.id,
            "name": str(section),  # Uses __str__ which prefers English name
        }
        for section in sections
    ]

    return JsonResponse(
        {"success": True, "location_id": location_id, "sections": sections_list, "count": len(sections_list)}
    )


@require_GET
def api_subsections(request, location_id, section_id):
    """
    API endpoint to get subsections for a specific location and section.

    Returns JSON list of subsections for given location and section.
    Public endpoint (no authentication required).
    """
    from apps.organizations.models import LegacySubSection

    subsections = LegacySubSection.objects.filter(location_id=location_id, main_section_id=section_id).order_by("name_en")

    subsections_list = [
        {
            "id": sub.internal_id,  # SubSection uses internal_id as primary key
            "name": str(sub),  # Uses __str__ which prefers English name
        }
        for sub in subsections
    ]

    return JsonResponse(
        {
            "success": True,
            "location_id": location_id,
            "section_id": section_id,
            "subsections": subsections_list,
            "count": len(subsections_list),
        }
    )


@require_GET
def api_departments(request, hospital_id):
    """
    API endpoint to get departments for a specific hospital.

    Returns JSON list of departments for given hospital.
    Public endpoint (no authentication required).
    """
    from apps.organizations.models import Department

    departments = Department.objects.filter(hospital_id=hospital_id, status="active").order_by("name")

    departments_list = [
        {
            "id": dept.id,
            "name": dept.name,  # Department model has 'name' field, not name_en
        }
        for dept in departments
    ]

    return JsonResponse(
        {"success": True, "hospital_id": hospital_id, "departments": departments_list, "count": len(departments_list)}
    )


def complaint_explanation_form(request, complaint_id, token):
    """
    Public-facing form for staff to submit explanation.

    This view does NOT require authentication.
    Validates token and checks if it's still valid (not used).
    """
    from .models import ComplaintExplanation, ExplanationAttachment
    from apps.notifications.services import NotificationService, get_email_header_html
    from django.contrib.sites.shortcuts import get_current_site

    # Get complaint
    complaint = get_object_or_404(Complaint, id=complaint_id)

    # Validate token with staff and department prefetch
    # Also prefetch escalation relationship to show original staff explanation to manager
    explanation = get_object_or_404(
        ComplaintExplanation.objects.select_related("staff", "staff__department", "staff__report_to").prefetch_related(
            "escalated_from_staff"
        ),
        complaint=complaint,
        token=token,
    )

    # Get original staff explanation if this is an escalation
    original_explanation = None
    if hasattr(explanation, "escalated_from_staff"):
        # This explanation was created as a result of escalation
        # Get the original staff explanation
        original_explanation = (
            ComplaintExplanation.objects.filter(escalated_to_manager=explanation).select_related("staff").first()
        )

    # Check if token is already used
    if explanation.is_used:
        return render(
            request,
            "complaints/explanation_already_submitted.html",
            {"complaint": complaint, "explanation": explanation},
        )

    if request.method == "POST":
        # Handle form submission
        explanation_text = request.POST.get("explanation", "").strip()

        if not explanation_text:
            return render(
                request,
                "complaints/explanation_form.html",
                {
                    "complaint": complaint,
                    "explanation": explanation,
                    "original_explanation": original_explanation,
                    "error": "Please provide your explanation.",
                },
            )

        # Save explanation
        explanation.explanation = explanation_text
        explanation.is_used = True
        explanation.responded_at = timezone.now()
        explanation.save()

        # Handle file attachments
        files = request.FILES.getlist("attachments")
        for uploaded_file in files:
            ExplanationAttachment.objects.create(
                explanation=explanation,
                file=uploaded_file,
                filename=uploaded_file.name,
                file_type=uploaded_file.content_type,
                file_size=uploaded_file.size,
            )

        # Populate the linked ComplaintInvolvedDepartment response for manager review
        from apps.complaints.models import ComplaintInvolvedDepartment
        involved_dept = ComplaintInvolvedDepartment.objects.filter(
            complaint=complaint,
            department=explanation.staff.department,
            sent=True,
        ).first()

        if involved_dept:
            involved_dept.response_notes = explanation_text
            involved_dept.response_notes_en = explanation_text
            involved_dept.response_submitted = True
            involved_dept.response_submitted_at = timezone.now()
            involved_dept.manager_review_status = "pending"
            involved_dept.manager_reviewed_by = None
            involved_dept.manager_reviewed_at = None
            involved_dept.acceptance_status = "pending"
            involved_dept.accepted_by = None
            involved_dept.accepted_at = None
            involved_dept.acceptance_notes = ""
            involved_dept.save()

            ComplaintUpdate.objects.create(
                complaint=complaint,
                update_type="note",
                message=f"Champion response submitted by {explanation.staff} from {involved_dept.department.name} — awaiting manager review",
                metadata={
                    "explanation_id": str(explanation.id),
                    "staff_id": str(explanation.staff.id) if explanation.staff else None,
                },
            )
        else:
            ComplaintUpdate.objects.create(
                complaint=complaint,
                update_type="communication",
                message=f"Explanation submitted by {explanation.staff}",
                metadata={
                    "explanation_id": str(explanation.id),
                    "staff_id": str(explanation.staff.id) if explanation.staff else None,
                },
            )

            # Fallback: notify PX Admin for explanations without linked InvolvedDepartment
            if complaint.assigned_to and complaint.assigned_to.email:
                site = get_current_site(request)
                complaint_url = f"https://{site.domain}/complaints/{complaint.id}/"
                try:
                    NotificationService.send_email(
                        email=complaint.assigned_to.email,
                        subject=f"New Explanation Received - Complaint #{complaint.reference_number}",
                        message=f"An explanation has been submitted for complaint {complaint.reference_number}.\n\nView: {complaint_url}",
                        related_object=complaint,
                        metadata={
                            "notification_type": "explanation_submitted",
                            "explanation_id": str(explanation.id),
                            "staff_id": str(explanation.staff.id) if explanation.staff else None,
                        },
                    )
                except Exception:
                    pass

        # Notify department manager to review (NOT the PX Admin)
        if involved_dept:
            dept = involved_dept.department
            if dept.manager and dept.manager.email:
                try:
                    review_url = request.build_absolute_uri(
                        reverse("organizations:department_manager_review", kwargs={"pk": dept.pk, "idept_pk": involved_dept.pk})
                    )
                    NotificationService.send_email(
                        dept.manager.email,
                        subject=f"Champion Response Requires Your Review - {complaint.reference_number}",
                        message=(
                            f"A champion response for complaint {complaint.reference_number} "
                            f"from {dept.name} requires your review and approval.\n\n"
                            f"Please review at: {review_url}"
                        ),
                        html_message=f"""
                        <div style="font-family: 'Segoe UI', Tahoma, sans-serif; max-width: 600px; margin: 0 auto; border: 1px solid #e5e7eb; border-radius: 8px; overflow: hidden;">
                            {get_email_header_html()}
                            <div style="padding: 20px;">
                                <h2 style="color: #005696; font-size: 18px; margin: 0 0 12px 0;">Champion Response Requires Your Review</h2>
                                <p>A champion from <strong>{dept.name}</strong> has submitted a response
                                for complaint <strong>{complaint.reference_number}</strong>.</p>
                                <p>Your review and approval is required before it is forwarded to the PX team.</p>
                                <p style="margin-top: 16px;">
                                    <a href="{review_url}" style="background: #005696; color: white; padding: 10px 24px; border-radius: 8px; text-decoration: none; font-weight: 600;">Review Response</a>
                                </p>
                            </div>
                        </div>
                        """,
                        related_object=complaint,
                    )
                except Exception as e:
                    import logging
                    logging.getLogger(__name__).error(f"Failed to send manager review notification: {e}")

        # Redirect to success page
        return render(
            request,
            "complaints/explanation_success.html",
            {"complaint": complaint, "explanation": explanation, "attachment_count": len(files)},
        )

    # GET request - display form
    from apps.complaints.models import ComplaintInvolvedStaff
    accused_staff = list(
        ComplaintInvolvedStaff.objects.filter(
            complaint=complaint, role=ComplaintInvolvedStaff.RoleChoices.ACCUSED
        ).select_related("staff")
    )

    existing_investigation = None
    if explanation.is_used:
        from apps.complaints.models import ChampionInvestigation
        existing_investigation = ChampionInvestigation.objects.filter(
            explanation=explanation
        ).select_related("champion").first()

    return render(
        request,
        "complaints/explanation_form.html",
        {
            "complaint": complaint,
            "explanation": explanation,
            "original_explanation": original_explanation,
            "accused_staff": accused_staff,
            "existing_investigation": existing_investigation,
            "investigate_url": request.build_absolute_uri(
                reverse("complaints:champion_start_investigation", kwargs={
                    "complaint_id": complaint.id,
                    "token": explanation.token,
                })
            ),
        },
    )


def champion_start_investigation(request, complaint_id, token):
    from .models import (
        ComplaintExplanation, ComplaintInvolvedStaff,
        ChampionInvestigation, InvestigationQuestion, InvestigationResponse,
        InvestigationAnswer, ComplaintUpdate,
    )
    from apps.notifications.services import NotificationService

    complaint = get_object_or_404(Complaint, id=complaint_id)
    explanation = get_object_or_404(
        ComplaintExplanation.objects.select_related("staff", "staff__department"),
        complaint=complaint, token=token,
    )

    if explanation.is_used:
        return render(request, "complaints/explanation_already_submitted.html", {
            "complaint": complaint, "explanation": explanation,
        })

    existing = ChampionInvestigation.objects.filter(explanation=explanation).first()
    if existing:
        return render(request, "complaints/investigation_already_started.html", {
            "complaint": complaint, "investigation": existing,
        })

    accused_staff = list(
        ComplaintInvolvedStaff.objects.filter(
            complaint=complaint, role=ComplaintInvolvedStaff.RoleChoices.ACCUSED
        ).select_related("staff")
    )

    if request.method == "POST":
        import secrets
        questions = request.POST.getlist("questions[]")
        questions = [q.strip() for q in questions if q.strip()]

        selected_staff_ids = request.POST.getlist("accused_staff[]")
        selected_staff_ids = [sid for sid in selected_staff_ids if sid]

        if not questions:
            return render(request, "complaints/investigation_questions.html", {
                "complaint": complaint,
                "explanation": explanation,
                "accused_staff": accused_staff,
                "error": "Please add at least one question.",
            })

        if not selected_staff_ids:
            return render(request, "complaints/investigation_questions.html", {
                "complaint": complaint,
                "explanation": explanation,
                "accused_staff": accused_staff,
                "error": "Please select at least one accused staff member.",
            })

        involved_dept = explanation.linked_involved_department

        investigation = ChampionInvestigation.objects.create(
            complaint=complaint,
            champion=explanation.staff,
            involved_department=involved_dept,
            explanation=explanation,
            status="questions_sent",
        )

        for i, q_text in enumerate(questions):
            InvestigationQuestion.objects.create(
                investigation=investigation,
                question_text=q_text,
                order=i + 1,
            )

        domain = request.get_host()
        staff_count = 0
        for sid in selected_staff_ids:
            staff_qs = accused_staff
            matched = next((s for s in staff_qs if str(s.staff_id) == sid), None)
            if not matched:
                try:
                    from apps.organizations.models import Staff
                    staff_obj = Staff.objects.get(id=sid)
                    matched = type('obj', (), {'staff': staff_obj, 'staff_id': staff_obj.id})()
                except Exception:
                    continue

            staff_member = matched.staff if hasattr(matched, 'staff') else matched
            resp_token = secrets.token_urlsafe(32)
            inv_response = InvestigationResponse.objects.create(
                investigation=investigation,
                staff=staff_member,
                token=resp_token,
            )

            for q in investigation.questions.all():
                InvestigationAnswer.objects.get_or_create(
                    response=inv_response, question=q, defaults={"answer_text": ""}
                )

            respond_url = f"https://{domain}/complaints/{complaint.id}/investigate/respond/{resp_token}/"

            staff_email = staff_member.email or (staff_member.user.email if hasattr(staff_member, 'user') and staff_member.user else None)
            if staff_email:
                try:
                    NotificationService.send_email(
                        email=staff_email,
                        subject=f"Investigation Questions - Complaint #{complaint.reference_number}",
                        message=(
                            f"Dear {staff_member.get_full_name()},\n\n"
                            f"You have been requested to answer investigation questions "
                            f"for complaint #{complaint.reference_number}.\n\n"
                            f"Please respond at: {respond_url}\n\n"
                            f"Note: This link can only be used once."
                        ),
                        html_message=f"""
                        <div style="font-family: 'Segoe UI', Tahoma, sans-serif; max-width: 600px; margin: 0 auto; border: 1px solid #e5e7eb; border-radius: 8px; overflow: hidden;">
                            {get_email_header_html()}
                            <div style="padding: 20px;">
                                <h2 style="color: #005696; font-size: 18px; margin: 0 0 12px 0;">Investigation Questions</h2>
                                <p>Dear <strong>{staff_member.get_full_name()}</strong>,</p>
                                <p>You have been requested to answer investigation questions for complaint
                                <strong>#{complaint.reference_number}</strong>.</p>
                                <p>The department champion would like your response before proceeding.</p>
                                <p style="margin-top: 16px;">
                                    <a href="{respond_url}" style="background: #005696; color: white; padding: 10px 24px; border-radius: 8px; text-decoration: none; font-weight: 600;">Answer Questions</a>
                                </p>
                                <p style="margin-top: 12px; font-size: 12px; color: #6b7280;">Note: This link can only be used once.</p>
                            </div>
                        </div>
                        """,
                        related_object=complaint,
                    )
                    inv_response.email_sent_at = timezone.now()
                    inv_response.save(update_fields=["email_sent_at"])
                except Exception as e:
                    import logging
                    logging.getLogger(__name__).error(f"Failed to send investigation email to {staff_email}: {e}")

            staff_phone = staff_member.phone or (staff_member.user.phone if hasattr(staff_member, 'user') and staff_member.user else None)
            if staff_phone:
                try:
                    NotificationService.send_sms(
                        to=staff_phone,
                        message=f"You have investigation questions for complaint #{complaint.reference_number}. Please respond at: {respond_url}",
                    )
                    inv_response.sms_sent_at = timezone.now()
                    inv_response.save(update_fields=["sms_sent_at"])
                except Exception as e:
                    import logging
                    logging.getLogger(__name__).error(f"Failed to send investigation SMS to {staff_phone}: {e}")

            staff_count += 1

        ComplaintUpdate.objects.create(
            complaint=complaint,
            update_type="note",
            message=f"Champion {explanation.staff.get_full_name()} started investigation — questions sent to {staff_count} staff member(s)",
            metadata={
                "investigation_id": str(investigation.id),
                "staff_count": staff_count,
            },
        )

        return render(request, "complaints/investigation_questions.html", {
            "complaint": complaint,
            "explanation": explanation,
            "accused_staff": accused_staff,
            "success": f"Investigation started. Questions sent to {staff_count} staff member(s).",
        })

    return render(request, "complaints/investigation_questions.html", {
        "complaint": complaint,
        "explanation": explanation,
        "accused_staff": accused_staff,
    })


def staff_investigation_form(request, complaint_id, token):
    from .models import (
        InvestigationResponse, InvestigationAnswer,
        ChampionInvestigation, ComplaintUpdate,
    )
    from apps.notifications.services import NotificationService, get_email_header_html

    complaint = get_object_or_404(Complaint, id=complaint_id)
    inv_response = get_object_or_404(
        InvestigationResponse.objects.select_related(
            "investigation", "investigation__champion", "staff"
        ).prefetch_related("investigation__questions"),
        token=token,
    )

    if inv_response.investigation.complaint_id != complaint.id:
        return render(request, "complaints/investigation_error.html", {
            "error": "Invalid link.",
        })

    if inv_response.is_completed:
        return render(request, "complaints/investigation_already_submitted.html", {
            "complaint": complaint, "inv_response": inv_response,
        })

    questions = list(inv_response.investigation.questions.all().order_by("order"))

    if request.method == "POST":
        for q in questions:
            answer_text = request.POST.get(f"question_{q.id}", "").strip()
            InvestigationAnswer.objects.update_or_create(
                response=inv_response,
                question=q,
                defaults={"answer_text": answer_text},
            )

        inv_response.is_completed = True
        inv_response.completed_at = timezone.now()
        inv_response.save(update_fields=["is_completed", "completed_at"])

        investigation = inv_response.investigation
        if investigation.all_responses_received:
            investigation.status = "answers_received"
            investigation.save(update_fields=["status"])

            champion = investigation.champion
            if champion and champion.email:
                domain = request.get_host()
                review_url = f"https://{domain}/complaints/{complaint.id}/investigate/review/{investigation.explanation.token}/"
                try:
                    NotificationService.send_email(
                        email=champion.email,
                        subject=f"All Investigation Responses Received - Complaint #{complaint.reference_number}",
                        message=(
                            f"Dear {champion.get_full_name()},\n\n"
                            f"All accused staff have responded to your investigation questions "
                            f"for complaint #{complaint.reference_number}.\n\n"
                            f"Please review and submit your final reply: {review_url}"
                        ),
                        html_message=f"""
<div style="font-family: 'Segoe UI', Tahoma, sans-serif; max-width: 600px; margin: 0 auto; border: 1px solid #e5e7eb; border-radius: 8px; overflow: hidden;">
    {get_email_header_html()}
    <div style="padding: 20px;">
        <h2 style="color: #005696; font-size: 18px; margin: 0 0 12px 0;">All Investigation Responses Received</h2>
        <p style="margin: 0 0 12px 0;">Dear {champion.get_full_name()},</p>
        <p style="margin: 0 0 12px 0;">All accused staff have responded to your investigation questions for complaint <strong>#{complaint.reference_number}</strong>.</p>
        <p style="margin: 0 0 12px 0;">Please review and submit your final reply.</p>
        <div style="text-align: center; margin: 20px 0;">
            <a href="{review_url}" style="background: #005696; color: white; padding: 10px 24px; border-radius: 8px; text-decoration: none; font-weight: 600;">Review &amp; Submit Reply</a>
        </div>
    </div>
</div>
""",
                        related_object=complaint,
                    )
                except Exception:
                    pass

        ComplaintUpdate.objects.create(
            complaint=complaint,
            update_type="note",
            message=f"Investigation response submitted by {inv_response.staff.get_full_name()}",
        )

        return render(request, "complaints/investigation_success.html", {
            "complaint": complaint,
            "inv_response": inv_response,
        })

    answers_map = {}
    for ans in InvestigationAnswer.objects.filter(response=inv_response).select_related("question"):
        answers_map[str(ans.question_id)] = ans.answer_text

    question_answer_pairs = []
    for q in questions:
        question_answer_pairs.append({
            "question": q,
            "existing_answer": answers_map.get(str(q.id), ""),
        })

    return render(request, "complaints/investigation_respond.html", {
        "complaint": complaint,
        "inv_response": inv_response,
        "question_answer_pairs": question_answer_pairs,
    })


def champion_review_answers(request, complaint_id, token):
    from .models import (
        ComplaintExplanation, ComplaintInvolvedDepartment,
        ChampionInvestigation, ComplaintUpdate,
    )
    from apps.notifications.services import NotificationService, get_email_header_html

    complaint = get_object_or_404(Complaint, id=complaint_id)
    explanation = get_object_or_404(
        ComplaintExplanation.objects.select_related("staff", "staff__department"),
        complaint=complaint, token=token,
    )

    investigation = ChampionInvestigation.objects.filter(
        explanation=explanation
    ).prefetch_related(
        "questions", "responses__staff", "responses__answers__question"
    ).first()

    if not investigation:
        return render(request, "complaints/investigation_error.html", {
            "error": "No investigation found for this complaint.",
        })

    if investigation.status == InvestigationStatus.REPLY_SUBMITTED:
        return render(request, "complaints/investigation_already_submitted.html", {
            "complaint": complaint, "investigation": investigation,
        })

    responses = list(investigation.responses.all().select_related("staff"))
    questions = list(investigation.questions.all().order_by("order"))

    answer_lookup = {}
    from .models import InvestigationAnswer
    for ans in InvestigationAnswer.objects.filter(
        response__investigation=investigation
    ).select_related("question"):
        key = (str(ans.response_id), str(ans.question_id))
        answer_lookup[key] = ans.answer_text

    staff_data = []
    for resp in responses:
        qa_pairs = []
        for q in questions:
            key = (str(resp.id), str(q.id))
            qa_pairs.append({
                "question": q,
                "answer": answer_lookup.get(key, ""),
            })
        staff_data.append({
            "response": resp,
            "staff": resp.staff,
            "is_completed": resp.is_completed,
            "qa_pairs": qa_pairs,
        })

    if request.method == "POST":
        final_reply = request.POST.get("final_reply", "").strip()
        if not final_reply:
            return render(request, "complaints/investigation_review.html", {
                "complaint": complaint,
                "explanation": explanation,
                "investigation": investigation,
                "questions": questions,
                "staff_data": staff_data,
                "error": "Please provide your final reply.",
            })

        investigation.final_reply = final_reply
        investigation.status = InvestigationStatus.REPLY_SUBMITTED
        investigation.save(update_fields=["final_reply", "status"])

        explanation.explanation = final_reply
        explanation.is_used = True
        explanation.responded_at = timezone.now()
        explanation.save(update_fields=["explanation", "is_used", "responded_at"])

        involved_dept = investigation.involved_department or explanation.linked_involved_department
        if involved_dept:
            involved_dept.response_notes = final_reply
            involved_dept.response_notes_en = final_reply
            involved_dept.response_submitted = True
            involved_dept.response_submitted_at = timezone.now()
            involved_dept.manager_review_status = "pending"
            involved_dept.manager_reviewed_by = None
            involved_dept.manager_reviewed_at = None
            involved_dept.acceptance_status = "pending"
            involved_dept.accepted_by = None
            involved_dept.accepted_at = None
            involved_dept.acceptance_notes = ""
            involved_dept.save()

            dept = involved_dept.department
            if dept and dept.manager and dept.manager.email:
                try:
                    review_url = request.build_absolute_uri(
                        reverse("organizations:department_manager_review", kwargs={
                            "pk": dept.pk,
                            "idept_pk": involved_dept.pk,
                        })
                    )
                    NotificationService.send_email(
                        dept.manager.email,
                        subject=f"Champion Response Requires Your Review - {complaint.reference_number}",
                        message=(
                            f"A champion response for complaint {complaint.reference_number} "
                            f"from {dept.name} requires your review and approval.\n\n"
                            f"Please review at: {review_url}"
                        ),
                        html_message=f"""
<div style="font-family: 'Segoe UI', Tahoma, sans-serif; max-width: 600px; margin: 0 auto; border: 1px solid #e5e7eb; border-radius: 8px; overflow: hidden;">
    {get_email_header_html()}
    <div style="padding: 20px;">
        <h2 style="color: #005696; font-size: 18px; margin: 0 0 12px 0;">Champion Response Requires Review</h2>
        <p style="margin: 0 0 12px 0;">A champion response for complaint <strong>{complaint.reference_number}</strong> from <strong>{dept.name}</strong> requires your review and approval.</p>
        <div style="text-align: center; margin: 20px 0;">
            <a href="{review_url}" style="background: #005696; color: white; padding: 10px 24px; border-radius: 8px; text-decoration: none; font-weight: 600;">Review Response</a>
        </div>
    </div>
</div>
""",
                        related_object=complaint,
                    )
                except Exception as e:
                    import logging
                    logging.getLogger(__name__).error(f"Failed to send manager review notification: {e}")

        files = request.FILES.getlist("attachments")
        from apps.complaints.models import ExplanationAttachment
        for f in files:
            ExplanationAttachment.objects.create(
                explanation=explanation,
                file=f,
                filename=f.name,
                file_type=f.content_type,
                file_size=f.size,
            )

        ComplaintUpdate.objects.create(
            complaint=complaint,
            update_type="note",
            message=f"Champion {explanation.staff.get_full_name()} submitted final reply after investigation — awaiting manager review",
            metadata={
                "investigation_id": str(investigation.id),
                "response_count": len(responses),
            },
        )

        return render(request, "complaints/explanation_success.html", {
            "complaint": complaint,
            "explanation": explanation,
            "attachment_count": len(files),
        })

    return render(request, "complaints/investigation_review.html", {
        "complaint": complaint,
        "explanation": explanation,
        "investigation": investigation,
        "questions": questions,
        "staff_data": staff_data,
    })


from django.http import HttpResponse
from django.utils.translation import gettext as _


def generate_complaint_pdf(request, pk):
    """
    Generate PDF for a complaint using WeasyPrint.

    Creates a professionally styled PDF document with all complaint details
    including AI analysis, staff assignment, and resolution information.
    """
    # Get complaint
    complaint = get_object_or_404(Complaint, id=pk)

    # Check permissions
    user = request.user
    if not user.is_authenticated:
        return HttpResponse("Unauthorized", status=401)

    # Check if user can view this complaint
    can_view = False
    if user.is_px_admin():
        can_view = True
    elif user.is_hospital_admin() and user.hospital == complaint.hospital:
        can_view = True
    elif user.is_department_manager() and user.department == complaint.department:
        can_view = True
    elif user.hospital == complaint.hospital:
        can_view = True

    if not can_view:
        return HttpResponse("Forbidden", status=403)

    # Render HTML template with comprehensive data
    from django.template.loader import render_to_string

    # Get explanations with their acceptance status
    explanations = complaint.explanations.all().select_related("staff", "accepted_by").prefetch_related("attachments")

    # Get timeline updates
    timeline = complaint.updates.all().select_related("created_by")[:20]  # Limit to last 20

    # Get related PX Actions
    from apps.px_action_center.models import PXAction
    from django.contrib.contenttypes.models import ContentType

    complaint_ct = ContentType.objects.get_for_model(Complaint)
    px_actions = PXAction.objects.filter(content_type=complaint_ct, object_id=complaint.id).order_by("-created_at")[:5]

    html_string = render_to_string(
        "complaints/complaint_pdf.html",
        {
            "complaint": complaint,
            "explanations": explanations,
            "timeline": timeline,
            "px_actions": px_actions,
            "generated_at": timezone.now(),
            "css_system_name": _("PX360 Complaint Management"),
            "css_page_label": _("Page"),
            "css_of_label": _("of"),
            "css_generated_label": _("Generated"),
        },
    )

    # Generate PDF using WeasyPrint
    try:
        from weasyprint import HTML

        pdf_file = HTML(string=html_string).write_pdf()

        # Create response
        response = HttpResponse(pdf_file, content_type="application/pdf")

        # Allow PDF to be displayed in iframe (same origin only)
        response["X-Frame-Options"] = "SAMEORIGIN"

        # Check if view=inline is requested (for iframe display)
        view_mode = request.GET.get("view", "download")
        if view_mode == "inline":
            # Display inline in browser
            response["Content-Disposition"] = "inline"
        else:
            # Download as attachment
            from datetime import datetime

            timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
            filename = f"complaint_{complaint.reference_number}_{timestamp}.pdf"
            response["Content-Disposition"] = f'attachment; filename="{filename}"'

        # Log audit
        AuditService.log_from_request(
            event_type="pdf_generated",
            description=f"PDF generated for complaint: {complaint.title}",
            request=request,
            content_object=complaint,
            metadata={"complaint_id": str(pk)},
        )

        return response
    except ImportError:
        return HttpResponse("WeasyPrint is not installed. Please install it to generate PDFs.", status=500)
    except Exception as e:
        import logging

        logger = logging.getLogger(__name__)
        logger.error(f"Error generating PDF for complaint {pk}: {e}")
        return HttpResponse(f"Error generating PDF: {str(e)}", status=500)


def inquiry_explanation_form(request, inquiry_id, token):
    """
    Public-facing form for staff to submit response to an inquiry.
    Does NOT require authentication. Validates token and checks validity.
    """
    from .models import InquiryExplanation, InquiryExplanationAttachment

    inquiry = get_object_or_404(Inquiry, id=inquiry_id)

    explanation = get_object_or_404(
        InquiryExplanation.objects.select_related("staff", "staff__department"),
        inquiry=inquiry,
        token=token,
    )

    if explanation.is_used:
        return render(
            request,
            "complaints/inquiry_explanation_already_submitted.html",
            {"inquiry": inquiry, "explanation": explanation},
        )

    if request.method == "POST":
        explanation_text = request.POST.get("explanation", "").strip()

        if not explanation_text:
            return render(
                request,
                "complaints/inquiry_explanation_form.html",
                {
                    "inquiry": inquiry,
                    "explanation": explanation,
                    "error": "Please provide your response.",
                },
            )

        explanation.explanation = explanation_text
        explanation.is_used = True
        explanation.responded_at = timezone.now()
        explanation.save()

        files = request.FILES.getlist("attachments")
        for uploaded_file in files:
            InquiryExplanationAttachment.objects.create(
                explanation=explanation,
                file=uploaded_file,
                filename=uploaded_file.name,
                file_type=uploaded_file.content_type,
                file_size=uploaded_file.size,
            )

        return render(
            request,
            "complaints/inquiry_explanation_success.html",
            {"inquiry": inquiry, "explanation": explanation},
        )

    return render(
        request,
        "complaints/inquiry_explanation_form.html",
        {"inquiry": inquiry, "explanation": explanation},
    )


def inquiry_respond_with_token(request, pk, token):
    """
    Public-facing form for department staff to submit response to an inquiry.
    Does NOT require authentication. Validates token and checks validity.
    """
    from apps.core.ai_service import AIService
    from apps.notifications.services import NotificationService
    from apps.core.utils import build_public_track_url

    inquiry = get_object_or_404(Inquiry, pk=pk)

    if inquiry.response_token != token or not inquiry.response_token:
        return render(request, "complaints/inquiry_response_token_invalid.html", {"inquiry": inquiry})

    if inquiry.response_token_used:
        return render(request, "complaints/inquiry_response_already_submitted.html", {"inquiry": inquiry})

    if request.method == "POST":
        response_en = request.POST.get("response_en", "").strip()
        response_ar = request.POST.get("response_ar", "").strip()
        response = response_en or response_ar

        if not response:
            return render(request, "complaints/inquiry_response_form_token.html", {
                "inquiry": inquiry,
                "error": "Please enter a response in at least one language.",
            })

        inquiry.department_response_en = response_en
        inquiry.department_response_ar = response_ar
        inquiry.department_responded_at = timezone.now()
        inquiry.dept_response_is_overdue = False
        inquiry.dept_response_acceptance_status = "pending"
        inquiry.response_token_used = True
        inquiry.save()

        # AI summary
        try:
            import json
            prompt = f"""Summarize the following department response to a patient inquiry in 2-3 concise sentences.

Inquiry subject: {inquiry.subject}
Inquiry message: {(inquiry.message or '')[:500]}
Department response: {response[:500]}

Generate JSON with "summary_en" and "summary_ar"."""
            result = AIService.chat_completion(prompt=prompt, response_format="json_object")
            parsed = json.loads(result)
            inquiry.department_response_summary_en = parsed.get("summary_en", "")
            inquiry.department_response_summary_ar = parsed.get("summary_ar", "")
            inquiry.save(update_fields=["department_response_summary_en", "department_response_summary_ar"])
        except Exception:
            pass

        # Notify inquirer
        track_url = build_public_track_url("inquiry", inquiry.reference_number)
        if inquiry.contact_phone:
            try:
                NotificationService.send_sms(
                    phone=inquiry.contact_phone,
                    message=f"PX360: Your inquiry {inquiry.reference_number} has been responded to. View: {track_url}",
                    related_object=inquiry,
                )
            except Exception:
                pass
        if inquiry.contact_email:
            try:
                NotificationService.send_email(
                    email=inquiry.contact_email,
                    subject=f"PX360: Response to Your Inquiry {inquiry.reference_number}",
                    message=f"Your inquiry has been responded to.\n\nView: {track_url}",
                    related_object=inquiry,
                )
            except Exception:
                pass

        return render(request, "complaints/inquiry_response_success_token.html", {"inquiry": inquiry})

    return render(request, "complaints/inquiry_response_form_token.html", {"inquiry": inquiry})
