"""
Notification Settings Views

Provides admin interface for configuring notification preferences.
"""

from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.core.exceptions import PermissionDenied
from django.core.paginator import Paginator
from django.shortcuts import render, redirect, get_object_or_404
from django.http import JsonResponse, HttpResponse
from django.utils.translation import gettext_lazy as _
from django.views.decorators.http import require_POST


def _get_notification_hospital(request, hospital_id=None):
    """Resolve hospital for notification views, using tenant_hospital for PX Admins."""
    if request.user.is_superuser and hospital_id:
        return get_object_or_404(Hospital, id=hospital_id)
    if request.user.is_px_admin():
        tenant = getattr(request, "tenant_hospital", None)
        if tenant:
            return tenant
        if hospital_id:
            return get_object_or_404(Hospital, id=hospital_id)
    if request.user.hospital:
        return request.user.hospital
    return None


from apps.organizations.models import Hospital
from .settings_models import HospitalNotificationSettings, NotificationSettingsLog


def can_manage_notifications(user):
    """Check if user can manage notification settings"""
    if user.is_superuser:
        return True
    if hasattr(user, "is_px_admin") and user.is_px_admin():
        return True
    if hasattr(user, "is_hospital_admin") and user.is_hospital_admin():
        return True
    return False


@login_required
def notification_settings_view(request, hospital_id=None):
    """
    Notification settings configuration page.

    Allows hospital admins to toggle notification preferences
    for different events and channels.
    """
    # Check permission
    if not can_manage_notifications(request.user):
        raise PermissionDenied("You do not have permission to manage notification settings.")

    # Get hospital
    hospital = _get_notification_hospital(request, hospital_id)
    if not hospital:
        if request.user.is_px_admin():
            return redirect("core:select_hospital")
        return redirect("core:no_hospital")
    hospital_id = hospital.id

    # Get or create settings
    settings = HospitalNotificationSettings.get_for_hospital(hospital_id)

    # Group settings by category for display
    notification_categories = [
        {
            "key": "complaint",
            "name": "Complaint Notifications",
            "icon": "bi-exclamation-triangle",
            "description": "Notifications related to complaint lifecycle",
            "events": [
                {
                    "key": "complaint_acknowledgment",
                    "name": "Complaint Acknowledgment",
                    "description": "Sent to patient when complaint is acknowledged",
                    "icon": "bi-check-circle",
                    "channels": ["email", "sms", "whatsapp"],
                },
                {
                    "key": "complaint_assigned",
                    "name": "Complaint Assigned",
                    "description": "Sent to staff when complaint is assigned to them",
                    "icon": "bi-person-check",
                    "channels": ["email", "sms", "whatsapp"],
                },
                {
                    "key": "complaint_status_changed",
                    "name": "Complaint Status Changed",
                    "description": "Sent when complaint status is updated",
                    "icon": "bi-arrow-repeat",
                    "channels": ["email", "sms", "whatsapp"],
                },
                {
                    "key": "complaint_resolved",
                    "name": "Complaint Resolved",
                    "description": "Sent to patient when complaint is resolved",
                    "icon": "bi-check2-all",
                    "channels": ["email", "sms", "whatsapp"],
                },
                {
                    "key": "complaint_closed",
                    "name": "Complaint Closed",
                    "description": "Sent to patient when complaint is closed",
                    "icon": "bi-x-circle",
                    "channels": ["email", "sms", "whatsapp"],
                },
            ],
        },
        {
            "key": "explanation",
            "name": "Explanation Notifications",
            "icon": "bi-chat-left-text",
            "description": "Notifications for staff explanation workflow",
            "events": [
                {
                    "key": "explanation_requested",
                    "name": "Explanation Requested",
                    "description": "Sent to staff when explanation is requested",
                    "icon": "bi-question-circle",
                    "channels": ["email", "sms", "whatsapp"],
                },
                {
                    "key": "explanation_reminder",
                    "name": "Explanation Reminder (24h)",
                    "description": "Reminder sent 24h before SLA deadline",
                    "icon": "bi-clock-history",
                    "channels": ["email", "sms", "whatsapp"],
                },
                {
                    "key": "explanation_overdue",
                    "name": "Explanation Overdue/Escalation",
                    "description": "Sent to manager when explanation is overdue",
                    "icon": "bi-exclamation-diamond",
                    "channels": ["email", "sms", "whatsapp"],
                },
                {
                    "key": "explanation_received",
                    "name": "Explanation Received",
                    "description": "Sent to assignee when staff submits explanation",
                    "icon": "bi-inbox",
                    "channels": ["email", "sms", "whatsapp"],
                },
            ],
            "extra_settings": [
                {
                    "key": "explanation_manager_cc",
                    "name": "Manager CC on Explanation Request",
                    "description": "CC manager when explanation is requested from staff",
                    "icon": "bi-person-badge",
                }
            ],
        },
        {
            "key": "survey",
            "name": "Survey Notifications",
            "icon": "bi-clipboard-check",
            "description": "Notifications for patient surveys",
            "events": [
                {
                    "key": "survey_invitation",
                    "name": "Survey Invitation",
                    "description": "Initial survey invitation sent to patient",
                    "icon": "bi-envelope-open",
                    "channels": ["email", "sms", "whatsapp"],
                },
                {
                    "key": "survey_reminder",
                    "name": "Survey Reminder",
                    "description": "Reminder for patients to complete survey",
                    "icon": "bi-bell",
                    "channels": ["email", "sms", "whatsapp"],
                },
                {
                    "key": "survey_completed",
                    "name": "Survey Completed",
                    "description": "Sent to admin when survey is completed",
                    "icon": "bi-check-circle-fill",
                    "channels": ["email", "sms"],
                },
            ],
        },
        {
            "key": "action",
            "name": "Action Plan Notifications",
            "icon": "bi-list-check",
            "description": "Notifications for action plan assignments",
            "events": [
                {
                    "key": "action_assigned",
                    "name": "Action Assigned",
                    "description": "Sent to staff when action is assigned",
                    "icon": "bi-person-plus",
                    "channels": ["email", "sms", "whatsapp"],
                },
                {
                    "key": "action_due_soon",
                    "name": "Action Due Soon",
                    "description": "Reminder when action is approaching deadline",
                    "icon": "bi-calendar-event",
                    "channels": ["email", "sms"],
                },
                {
                    "key": "action_overdue",
                    "name": "Action Overdue",
                    "description": "Alert when action is past deadline",
                    "icon": "bi-calendar-x",
                    "channels": ["email", "sms"],
                },
            ],
        },
        {
            "key": "sla",
            "name": "SLA Notifications",
            "icon": "bi-stopwatch",
            "description": "Notifications for SLA monitoring",
            "events": [
                {
                    "key": "sla_reminder",
                    "name": "SLA Reminder",
                    "description": "Reminder before SLA breach",
                    "icon": "bi-clock",
                    "channels": ["email", "sms"],
                },
                {
                    "key": "sla_breach",
                    "name": "SLA Breach Alert",
                    "description": "Alert when SLA is breached",
                    "icon": "bi-exclamation-octagon",
                    "channels": ["email", "sms", "whatsapp"],
                },
            ],
        },
        {
            "key": "onboarding",
            "name": "Onboarding Notifications",
            "icon": "bi-person-plus",
            "description": "Notifications for user onboarding and acknowledgements",
            "events": [
                {
                    "key": "onboarding_invitation",
                    "name": "Onboarding Invitation",
                    "description": "Sent to new provisional users to complete registration",
                    "icon": "bi-envelope-plus",
                    "channels": ["email", "sms", "whatsapp"],
                },
                {
                    "key": "onboarding_reminder",
                    "name": "Onboarding Reminder",
                    "description": "Reminder to complete onboarding before invitation expires",
                    "icon": "bi-bell",
                    "channels": ["email", "sms", "whatsapp"],
                },
                {
                    "key": "onboarding_completion",
                    "name": "Onboarding Completion",
                    "description": "Sent to admins when user completes onboarding",
                    "icon": "bi-check-circle-fill",
                    "channels": ["email", "sms"],
                },
            ],
        },
    ]

    # Get recent change logs
    change_logs = (
        NotificationSettingsLog.objects.filter(hospital=hospital)
        .select_related("changed_by")
        .order_by("-created_at")[:10]
    )

    context = {
        "hospital": hospital,
        "settings": settings,
        "categories": notification_categories,
        "change_logs": change_logs,
        "is_superuser": request.user.is_superuser,
    }

    return render(request, "notifications/settings.html", context)


@login_required
@require_POST
def notification_settings_update(request, hospital_id=None):
    """
    Update notification settings via AJAX or form POST.
    """
    # Check permission
    if not can_manage_notifications(request.user):
        raise PermissionDenied("You do not have permission to manage notification settings.")

    # Get hospital
    hospital = _get_notification_hospital(request, hospital_id)
    if not hospital:
        if request.headers.get("X-Requested-With") == "XMLHttpRequest":
            return JsonResponse({"success": False, "error": "No hospital assigned"}, status=400)
        messages.error(request, "No hospital assigned. Please contact your administrator.")
        return redirect("analytics:command_center")

    settings = HospitalNotificationSettings.get_for_hospital(hospital.id)

    # Handle master switch
    if "notifications_enabled" in request.POST:
        old_value = settings.notifications_enabled
        new_value = request.POST.get("notifications_enabled") == "on"
        settings.notifications_enabled = new_value
        settings.save()

        NotificationSettingsLog.objects.create(
            hospital=hospital,
            changed_by=request.user,
            field_name="notifications_enabled",
            old_value=old_value,
            new_value=new_value,
        )

        if request.headers.get("X-Requested-With") == "XMLHttpRequest":
            return JsonResponse({"success": True, "message": f"Notifications {'enabled' if new_value else 'disabled'}"})
        messages.success(request, f"Notifications {'enabled' if new_value else 'disabled'}")
        return redirect("notifications:settings_with_hospital", hospital_id=hospital.id)

    # Handle individual toggle
    field_name = request.POST.get("field")
    value = request.POST.get("value") == "true"

    if field_name and hasattr(settings, field_name):
        old_value = getattr(settings, field_name)
        setattr(settings, field_name, value)
        settings.save()

        # Log the change
        NotificationSettingsLog.objects.create(
            hospital=hospital, changed_by=request.user, field_name=field_name, old_value=old_value, new_value=value
        )

        if request.headers.get("X-Requested-With") == "XMLHttpRequest":
            return JsonResponse({"success": True, "field": field_name, "value": value})

        messages.success(request, "Setting updated successfully")
    else:
        if request.headers.get("X-Requested-With") == "XMLHttpRequest":
            return JsonResponse({"success": False, "error": "Invalid field name"}, status=400)
        messages.error(request, "Invalid setting")

    return redirect("notifications:settings_with_hospital", hospital_id=hospital.id)


@login_required
@require_POST
def update_quiet_hours(request, hospital_id=None):
    """
    Update quiet hours settings.
    """
    # Check permission
    if not can_manage_notifications(request.user):
        raise PermissionDenied("You do not have permission to manage notification settings.")

    hospital = _get_notification_hospital(request, hospital_id)
    if not hospital:
        messages.error(request, "No hospital assigned. Please contact your administrator.")
        return redirect("analytics:command_center")

    settings = HospitalNotificationSettings.get_for_hospital(hospital.id)

    settings.quiet_hours_enabled = request.POST.get("quiet_hours_enabled") == "on"
    settings.quiet_hours_start = request.POST.get("quiet_hours_start", "22:00")
    settings.quiet_hours_end = request.POST.get("quiet_hours_end", "08:00")
    settings.save()

    messages.success(request, "Quiet hours settings updated")
    return redirect("notifications:settings_with_hospital", hospital_id=hospital.id)


@login_required
def test_notification(request, hospital_id=None):
    """
    Send a test notification to verify settings.
    """
    # Check permission
    if not can_manage_notifications(request.user):
        raise PermissionDenied("You do not have permission to manage notification settings.")

    hospital = _get_notification_hospital(request, hospital_id)
    if not hospital:
        messages.error(request, "No hospital assigned. Please contact your administrator.")
        return redirect("analytics:command_center")

    settings = HospitalNotificationSettings.get_for_hospital(hospital.id)
    channel = request.POST.get("channel", "email")

    from .services import NotificationService, get_email_header_html

    if channel == "email" and request.user.email:
        NotificationService.send_email(
            email=request.user.email,
            subject="PX360 Test Notification",
            message="This is a test notification from PX360.\n\nIf you received this, your email notifications are working correctly.",
            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;">Test Notification</h2>
        <p style="margin: 0 0 12px 0;">This is a test notification from PX360.</p>
        <p style="margin: 0; color: #6b7280;">If you received this, your email notifications are working correctly.</p>
    </div>
</div>
""",
            metadata={"test": True, "hospital_id": str(hospital.id)},
        )
        messages.success(request, f"Test email sent to {request.user.email}")

    elif channel == "sms":
        phone = request.POST.get("test_phone")
        if phone:
            NotificationService.send_sms(
                phone=phone,
                message="PX360 Test: Your SMS notifications are configured correctly.",
                metadata={"test": True, "hospital_id": str(hospital.id)},
            )
            messages.success(request, f"Test SMS sent to {phone}")
        else:
            messages.error(request, "Please provide a phone number")

    else:
        messages.error(request, "Invalid channel selected")

    return redirect("notifications:settings_with_hospital", hospital_id=hospital.id)


@login_required
def notification_settings_api(request, hospital_id=None):
    """
    API endpoint to get current notification settings as JSON.
    Useful for AJAX updates and mobile apps.
    """
    hospital = _get_notification_hospital(request, hospital_id)
    if not hospital:
        return JsonResponse({"error": "No hospital assigned"}, status=400)

    settings = HospitalNotificationSettings.get_for_hospital(hospital.id)

    # Build response with all settings
    settings_dict = {}
    for field in settings._meta.fields:
        if field.name not in ["id", "uuid", "created_at", "updated_at", "hospital"]:
            settings_dict[field.name] = getattr(settings, field.name)

    return JsonResponse(
        {"hospital_id": str(hospital.id), "hospital_name": hospital.get_display_name(), "settings": settings_dict}
    )


@login_required
def send_sms_direct(request):
    """
        Direct SMS sending page for admins.

        Allows PX Admins and Hospital Admins to send SMS messages
    directly to any phone number.
    """
    from .services import NotificationService

    # Check permission - only admins can send direct SMS
    if not can_manage_notifications(request.user):
        raise PermissionDenied("You do not have permission to send SMS messages.")

    if request.method == "POST":
        phone_number = request.POST.get("phone_number", "").strip()
        message = request.POST.get("message", "").strip()

        # Validate inputs
        errors = []
        if not phone_number:
            errors.append(_("Phone number is required."))
        elif not phone_number.startswith("+"):
            errors.append(_("Phone number must include country code (e.g., +966501234567)."))

        if not message:
            errors.append(_("Message is required."))
        elif len(message) > 1600:
            errors.append(_("Message is too long. Maximum 1600 characters."))

        if errors:
            for error in errors:
                messages.error(request, error)
            return render(
                request,
                "notifications/send_sms_direct.html",
                {
                    "phone_number": phone_number,
                    "message": message,
                },
            )

        try:
            # Clean phone number
            phone_number = phone_number.replace(" ", "").replace("-", "").replace("(", "").replace(")", "")

            # Send SMS
            notification_log = NotificationService.send_sms(
                phone=phone_number,
                message=message,
                metadata={
                    "sent_by": str(request.user.id),
                    "sent_by_name": request.user.get_full_name(),
                    "source": "direct_sms_send",
                },
            )

            # Log the action
            from apps.core.services import AuditService

            AuditService.log_event(
                event_type="sms_sent_direct",
                description=f"Direct SMS sent to {phone_number} by {request.user.get_full_name()}",
                user=request.user,
                metadata={
                    "phone_number": phone_number,
                    "message_length": len(message),
                    "notification_log_id": str(notification_log.id) if notification_log else None,
                },
            )

            messages.success(request, _(f"SMS sent successfully to {phone_number}."))
            return redirect("notifications:send_sms_direct")

        except Exception as e:
            import logging

            logger = logging.getLogger(__name__)
            logger.error(f"Error sending direct SMS: {str(e)}", exc_info=True)
            messages.error(request, f"Error sending SMS: {str(e)}")

    return render(request, "notifications/send_sms_direct.html")


# ============================================================================
# NOTIFICATION INBOX VIEWS
# ============================================================================


@login_required
def notification_inbox(request):
    """
    Notification inbox page.
    Displays all non-dismissed notifications for the current user.
    """
    from .models import UserNotification

    filter_type = request.GET.get("filter", "all")

    # Base queryset - exclude dismissed
    notifications = UserNotification.objects.filter(user=request.user, is_dismissed=False)

    # Apply filters
    if filter_type == "unread":
        notifications = notifications.filter(is_read=False)
    elif filter_type == "read":
        notifications = notifications.filter(is_read=True)

    # Pagination
    paginator = Paginator(notifications, 20)
    page = request.GET.get("page", 1)
    notifications_page = paginator.get_page(page)

    context = {
        "notifications": notifications_page,
        "filter": filter_type,
        "unread_count": UserNotification.objects.filter(user=request.user, is_read=False, is_dismissed=False).count(),
    }

    return render(request, "notifications/inbox.html", context)


@login_required
def notification_list_api(request):
    """
    API endpoint to get notifications list (JSON).
    """
    from .models import UserNotification
    from django.http import JsonResponse

    filter_type = request.GET.get("filter", "all")
    page = int(request.GET.get("page", 1))

    notifications = UserNotification.objects.filter(user=request.user, is_dismissed=False)

    if filter_type == "unread":
        notifications = notifications.filter(is_read=False)
    elif filter_type == "read":
        notifications = notifications.filter(is_read=True)

    paginator = Paginator(notifications, 20)
    notifications_page = paginator.get_page(page)

    data = {
        "notifications": [
            {
                "id": str(n.id),
                "title": n.get_title(),
                "message": n.get_message(),
                "type": n.notification_type,
                "is_read": n.is_read,
                "created_at": n.created_at.isoformat(),
                "action_url": n.action_url,
            }
            for n in notifications_page
        ],
        "has_next": notifications_page.has_next(),
        "has_previous": notifications_page.has_previous(),
        "page": page,
        "total_pages": paginator.num_pages,
    }

    return JsonResponse(data)


@login_required
@require_POST
def mark_notification_read(request, notification_id):
    """
    Mark a single notification as read.
    """
    from .models import UserNotification
    from django.http import JsonResponse

    try:
        notification = UserNotification.objects.get(id=notification_id, user=request.user)
        notification.mark_as_read()
        return JsonResponse({"success": True})
    except UserNotification.DoesNotExist:
        return JsonResponse({"success": False, "error": "Notification not found"}, status=404)


@login_required
@require_POST
def mark_all_notifications_read(request):
    """
    Mark all notifications as read.
    """
    from .models import UserNotification
    from django.http import JsonResponse
    from django.utils import timezone

    UserNotification.objects.filter(user=request.user, is_read=False, is_dismissed=False).update(
        is_read=True, read_at=timezone.now()
    )

    return JsonResponse({"success": True})


@login_required
@require_POST
def dismiss_notification(request, notification_id):
    """
    Dismiss a notification.
    """
    from .models import UserNotification
    from django.http import JsonResponse

    try:
        notification = UserNotification.objects.get(id=notification_id, user=request.user)
        notification.mark_as_dismissed()
        return JsonResponse({"success": True})
    except UserNotification.DoesNotExist:
        return JsonResponse({"success": False, "error": "Notification not found"}, status=404)


@login_required
@require_POST
def dismiss_all_notifications(request):
    """
    Dismiss all notifications.
    """
    from .models import UserNotification
    from django.http import JsonResponse
    from django.utils import timezone

    UserNotification.objects.filter(user=request.user, is_dismissed=False).update(
        is_dismissed=True, dismissed_at=timezone.now()
    )

    return JsonResponse({"success": True})


@login_required
def unread_notification_count(request):
    """
    Get unread notification count.
    """
    from .models import UserNotification
    from django.http import JsonResponse

    count = UserNotification.objects.filter(user=request.user, is_read=False, is_dismissed=False).count()

    return JsonResponse({"count": count})


@login_required
def latest_notifications(request):
    """
    Get latest 5 unread notifications for dropdown.
    """
    from .models import UserNotification
    from django.http import JsonResponse

    notifications = UserNotification.objects.filter(user=request.user, is_read=False, is_dismissed=False)[:5]

    data = {
        "notifications": [
            {
                "id": str(n.id),
                "title": n.get_title(),
                "message": n.get_message()[:100] + "..." if len(n.get_message()) > 100 else n.get_message(),
                "type": n.notification_type,
                "created_at": n.created_at.isoformat(),
                "action_url": n.action_url,
            }
            for n in notifications
        ],
        "has_more": UserNotification.objects.filter(user=request.user, is_read=False, is_dismissed=False).count() > 5,
    }

    return JsonResponse(data)
