"""
Core views - Health check and utility views
"""

from django.contrib.auth.decorators import login_required
from django.contrib import messages
from django.db import connection
from django.http import JsonResponse
from django.shortcuts import redirect, render
from django.utils.translation import gettext_lazy as _
from django.views.decorators.cache import never_cache
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_GET, require_POST, require_http_methods


@never_cache
@require_GET
def health_check(request):
    """
    Health check endpoint for monitoring and load balancers.
    Returns JSON with status of various services.
    """
    health_status = {"status": "ok", "services": {}}

    # Check database connection
    try:
        with connection.cursor() as cursor:
            cursor.execute("SELECT 1")
        health_status["services"]["database"] = "ok"
    except Exception as e:
        health_status["status"] = "error"
        health_status["services"]["database"] = f"error: {str(e)}"

    # Check Redis/Celery (optional - don't fail if not available)
    try:
        from django_celery_beat.models import PeriodicTask

        PeriodicTask.objects.count()
        health_status["services"]["celery_beat"] = "ok"
    except Exception:
        health_status["services"]["celery_beat"] = "not_configured"

    # Return appropriate status code
    status_code = 200 if health_status["status"] == "ok" else 503

    return JsonResponse(health_status, status=status_code)


@login_required
def select_hospital(request):
    """
    Hospital selection page for PX Admins.

    Allows PX Admins to switch between hospitals.
    Stores selected hospital in session.
    """
    # Only PX Admins should access this page
    if not request.user.is_px_admin():
        return redirect("dashboard:dashboard")

    from apps.organizations.models import Hospital

    hospitals = Hospital.objects.all().order_by("name")

    # Handle hospital selection
    if request.method == "POST":
        hospital_id = request.POST.get("hospital_id")
        if hospital_id:
            try:
                hospital = Hospital.objects.get(id=hospital_id)
                request.session["selected_hospital_id"] = str(hospital.id)
                # Redirect to referring page or dashboard
                next_url = request.POST.get("next", request.GET.get("next", "/"))
                return redirect(next_url)
            except Hospital.DoesNotExist:
                pass

    context = {
        "hospitals": hospitals,
        "selected_hospital_id": request.session.get("selected_hospital_id"),
        "next": request.GET.get("next", "/"),
    }

    return render(request, "core/select_hospital.html", context)


@login_required
@require_POST
def switch_hospital(request):
    """
    AJAX endpoint to switch hospitals for PX Admins.

    Stores selected hospital in session and returns JSON response.
    """
    # Only PX Admins can switch hospitals
    if not request.user.is_px_admin():
        return JsonResponse(
            {"success": False, "error": "Permission denied. Only PX Admins can switch hospitals."}, status=403
        )

    from apps.organizations.models import Hospital

    hospital_id = request.POST.get("hospital_id")

    if not hospital_id:
        return JsonResponse({"success": False, "error": "Hospital ID is required"}, status=400)

    try:
        hospital = Hospital.objects.get(id=hospital_id)
        request.session["selected_hospital_id"] = str(hospital.id)

        return JsonResponse(
            {
                "success": True,
                "hospital": {
                    "id": str(hospital.id),
                    "name": hospital.name,
                    "display_name": hospital.get_display_name(),
                    "display_name_ar": hospital.get_display_name_ar(),
                    "code": hospital.code,
                },
            }
        )
    except Hospital.DoesNotExist:
        return JsonResponse({"success": False, "error": "Hospital not found"}, status=404)


@login_required
def no_hospital_assigned(request):
    """
    Error page for users without a hospital assigned.

    Users without a hospital assignment cannot access the system.
    """
    return render(request, "core/no_hospital_assigned.html", status=403)


# ============================================================================
# PUBLIC SUBMISSION VIEWS
# ============================================================================


def public_submit_landing(request):
    """
    Landing page for public submissions.

    Allows users to choose between Complaint, Observation, or Inquiry.
    No authentication required.
    """
    from apps.organizations.models import Hospital

    if request.method == "POST":
        # Return 405 Method Not Allowed with proper JSON response
        from django.http import JsonResponse

        return JsonResponse(
            {"success": False, "error": "Method not allowed. Please use GET to access the landing page."}, status=405
        )

    hospitals = Hospital.objects.all().order_by("name")

    context = {
        "hospitals": hospitals,
    }

    return render(request, "core/public_submit.html", context)


@require_POST
def public_inquiry_submit(request):
    """
    Handle public inquiry submissions.

    Creates an inquiry from public submission.
    Returns JSON response with reference number.
    """
    from apps.complaints.models import Inquiry
    from apps.organizations.models import Hospital, Department, Section, OrgSubSection
    import uuid

    name = request.POST.get("name", "").strip()
    email = request.POST.get("email", "").strip()
    phone = request.POST.get("phone", "").strip()
    hospital_id = request.POST.get("hospital")
    location_type = request.POST.get("location_type", "").strip()
    area_id = request.POST.get("area", "").strip()
    category = request.POST.get("category", "").strip()
    subject = request.POST.get("subject", "").strip()
    message = request.POST.get("message", "").strip()
    department_id = request.POST.get("department", "").strip()
    section_id = request.POST.get("section", "").strip()

    # Validation
    errors = []

    if not name:
        errors.append("Name is required")
    if not phone:
        errors.append("Phone number is required")
    if not hospital_id:
        errors.append("Hospital selection is required")
    if not message:
        errors.append("Message is required")

    if errors:
        return JsonResponse({"success": False, "errors": errors}, status=400)

    try:
        # Validate hospital
        hospital = Hospital.objects.get(id=hospital_id)

        from apps.organizations.models import Area

        department = Department.objects.filter(id=department_id).first() if department_id else None
        section = Section.objects.filter(id=section_id).first() if section_id else None
        area = Area.objects.filter(id=area_id).first() if area_id else None

        inquiry = Inquiry.objects.create(
            hospital=hospital,
            contact_name=name,
            contact_email=email,
            contact_phone=phone,
            subject=subject,
            message=message,
            category=category,
            status="open",
            area=area,
            department=department,
            section=section,
            location_type=location_type if location_type else "",
        )

        reference_number = inquiry.reference_number  # generated by Inquiry.save() (unified format)

        try:
            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))
        except Exception:
            pass

        try:
            from apps.core.services import AuditService
            AuditService.log_event(
                event_type="inquiry_created_public",
                description=f"Public inquiry submitted: {subject}",
                content_object=inquiry,
                metadata={"reference": reference_number, "source": "public_form"},
            )
        except Exception:
            pass

        # Send notification email (optional)
        try:
            from django.core.mail import send_mail
            from django.conf import settings
            from django.template.loader import render_to_string

            email_subject = f"New Public Inquiry - {reference_number}"
            html_message = render_to_string(
                "emails/public_inquiry_notification.html",
                {
                    "name": name,
                    "subject": subject,
                    "message": message,
                    "reference_number": reference_number,
                },
            )
            plain_message = f"Inquiry from {name}\n\nSubject: {subject}\n\nMessage:\n{message}"
            send_mail(
                subject=email_subject,
                message=plain_message,
                from_email=settings.DEFAULT_FROM_EMAIL,
                recipient_list=[settings.DEFAULT_FROM_EMAIL],
                fail_silently=True,
                html_message=html_message,
            )
        except Exception:
            pass  # Don't fail if email doesn't send

        return JsonResponse({"success": True, "reference_number": reference_number, "inquiry_id": str(inquiry.id)})

    except Hospital.DoesNotExist:
        return JsonResponse({"success": False, "errors": ["Invalid hospital selected"]}, status=400)
    except Exception as e:
        return JsonResponse({"success": False, "errors": [str(e)]}, status=500)


@require_GET
def api_hospitals(request):
    """
    API endpoint to get hospitals list.

    Used by public submission forms to populate hospital dropdown.
    """
    from apps.organizations.models import Hospital

    hospitals = Hospital.objects.all().order_by("name").values("id", "name")

    return JsonResponse({"success": True, "hospitals": list(hospitals)})


@require_GET
def set_language(request):
    """
    Set's language preference for the session and cookie.

    Stores the selected language in session and sets a persistent cookie
    for better reliability across page reloads and incognito sessions.
    """
    from django.conf import settings
    from django.utils import translation
    from urllib.parse import urlparse

    language = request.GET.get("language", "en")

    # Validate language code
    if language not in dict(settings.LANGUAGES):
        language = "en"

    # Activate and store the language in session
    translation.activate(language)
    request.session["django_language"] = language

    # Explicitly save the session to ensure it persists
    if hasattr(request, "session") and request.session.modified:
        request.session.save()

    # Get the referring URL or use a default
    next_url = request.META.get("HTTP_REFERER", "/")
    parsed_url = urlparse(next_url)

    # Keep the path but remove query parameters if needed
    redirect_url = parsed_url.path if parsed_url.path else "/"

    # If there's no referer, redirect to home or public submit landing
    if next_url == "/" or not next_url:
        redirect_url = "/"

    # Create response with redirect
    response = redirect(redirect_url)

    # Also set a persistent cookie as a fallback mechanism
    # This ensures language persists even if session storage fails
    response.set_cookie(
        "django_language",
        language,
        max_age=365 * 24 * 60 * 60,  # 1 year
        httponly=False,  # Allow JavaScript to read it if needed
        secure=False,  # Allow over HTTP for local development
        samesite="Lax",  # Standard SameSite policy
    )

    return response


@require_GET
def api_observation_categories(request):
    """
    API endpoint to get observation categories list.

    Used by public observation form to populate category dropdown.
    """
    from apps.observations.models import ObservationCategory

    categories = (
        ObservationCategory.objects.filter(is_active=True)
        .order_by("sort_order", "name_en")
        .values("id", "name_en", "name_ar")
    )

    return JsonResponse({"success": True, "categories": list(categories)})


def public_track(request):
    """
    Unified public tracking page.

    Allows users to track complaints, inquiries, and observations
    from a single page. Shows 3 selection cards, then inline results.
    """
    return render(request, "core/public_track.html", {})


@require_GET
def public_track_api(request):
    """
    API endpoint for unified tracking.

    Accepts an optional type (complaint/inquiry/observation) and a reference.
    If type is omitted, it is auto-detected from the reference prefix
    (CMP/INQ/OBS). APR and SGT references are internal-only and not tracked.

    Returns standardized JSON with tracking information.
    """
    from django.utils.translation import gettext as _

    track_type = request.GET.get("type", "").strip().lower()
    reference = request.GET.get("reference", "").strip()

    if not reference:
        return JsonResponse({"found": False, "error": str(_("A reference number is required."))}, status=400)

    # Auto-detect type from prefix when not provided
    if not track_type:
        upper = reference.upper()
        if upper.startswith("CMP-"):
            track_type = "complaint"
        elif upper.startswith("INQ-"):
            track_type = "inquiry"
        elif upper.startswith("OBS-"):
            track_type = "observation"
        elif upper.startswith(("APR-", "SGT-")):
            return JsonResponse(
                {"found": False, "error": str(_("This reference type is not publicly trackable."))},
                status=400,
            )
        else:
            return JsonResponse({"found": False, "error": str(_("Unrecognized reference format."))}, status=400)

    if track_type == "complaint":
        return _track_complaint(reference)
    elif track_type == "inquiry":
        return _track_inquiry(reference)
    elif track_type == "observation":
        return _track_observation(reference)
    else:
        return JsonResponse({"found": False, "error": str(_("Invalid tracking type."))}, status=400)


def _track_complaint(reference):
    from apps.complaints.models import Complaint, ComplaintInvolvedDepartment

    try:
        complaint = (
            Complaint.objects.select_related("hospital", "department", "legacy_location")
            .prefetch_related("updates")
            .get(reference_number__iexact=reference)
        )
        complaint.check_overdue()
    except Complaint.DoesNotExist:
        return JsonResponse({"found": False, "error": "Complaint not found"})

    ps = complaint.public_status

    public_updates = list(
        complaint.updates.filter(update_type__in=["status_change", "resolution"])
        .order_by("-created_at")[:20]
    )

    _status_map = {
        "open": "Received", "in_progress": "In Progress",
        "partially_resolved": "In Progress", "contacted": "In Progress",
        "contacted_no_response": "In Progress", "resolved": "Resolved",
        "closed": "Closed", "cancelled": "Cancelled",
    }

    timeline = []
    for u in public_updates:
        icon = "refresh-cw" if u.update_type == "status_change" else "check-circle-2"
        title = "Status Updated" if u.update_type == "status_change" else "Final Resolution"
        msg = u.message or ""
        for internal, public_label in _status_map.items():
            msg = msg.replace(internal, public_label)
        timeline.append({
            "type": u.update_type,
            "icon": icon,
            "title": title,
            "comment": msg,
            "created_at": u.created_at.strftime("%Y-%m-%d %H:%M"),
        })

    info_cards = [
        {"icon": "calendar", "label": "Submitted", "value": complaint.created_at.strftime("%b %d, %Y")},
        {"icon": "building", "label": "Department", "value": complaint.department.name if complaint.department else "General"},
    ]
    if complaint.due_at:
        info_cards.append({
            "icon": "clock",
            "label": "SLA Deadline",
            "value": complaint.due_at.strftime("%b %d, %H:%M"),
            "alert": complaint.is_overdue,
        })
    else:
        info_cards.append({"icon": "tag", "label": "Category", "value": complaint.get_category_display() if hasattr(complaint, 'get_category_display') else "General"})

    response = {"has_response": False, "en": "", "ar": ""}
    if complaint.status in ("resolved", "closed") and complaint.resolution:
        response = {"has_response": True, "en": complaint.resolution, "ar": ""}

    return JsonResponse({
        "found": True,
        "type": "complaint",
        "reference": complaint.reference_number,
        "status": ps["slug"],
        "status_display": ps["label"],
        "progress": ps["progress"],
        "status_color": ps["css"],
        "escalated": bool(complaint.escalated_at),
        "info_cards": info_cards,
        "timeline": timeline,
        "response": response,
        "satisfaction": complaint.satisfaction or "",
        "satisfaction_set_at": complaint.satisfaction_set_at.strftime("%Y-%m-%d %H:%M") if complaint.satisfaction_set_at else None,
    })


def _track_inquiry(reference):
    from apps.complaints.models import Inquiry

    inquiry = Inquiry.objects.filter(reference_number__iexact=reference).select_related("hospital", "department").first()
    if not inquiry:
        return JsonResponse({"found": False, "error": "Inquiry not found"})

    status_map = {
        "open": {"label": "Received", "progress": 15, "css": "amber"},
        "in_progress": {"label": "In Progress", "progress": 50, "css": "blue"},
        "resolved": {"label": "Resolved", "progress": 100, "css": "emerald"},
        "closed": {"label": "Closed", "progress": 100, "css": "slate"},
    }
    sm = status_map.get(inquiry.status, {"label": inquiry.get_status_display(), "progress": 15, "css": "amber"})

    timeline = []
    if inquiry.status in ("resolved", "closed") and (inquiry.department_response_en or inquiry.department_response_ar):
        timeline.append({
            "type": "response",
            "icon": "check-circle-2",
            "title": "Response Sent",
            "comment": "",
            "created_at": (inquiry.department_responded_at or inquiry.updated_at).strftime("%Y-%m-%d %H:%M"),
        })

    info_cards = [
        {"icon": "calendar", "label": "Submitted", "value": inquiry.created_at.strftime("%b %d, %Y")},
        {"icon": "building", "label": "Department", "value": inquiry.department.name if inquiry.department else "General"},
    ]
    if inquiry.due_at:
        info_cards.append({
            "icon": "clock",
            "label": "SLA Deadline",
            "value": inquiry.due_at.strftime("%b %d, %H:%M"),
            "alert": inquiry.is_overdue,
        })
    else:
        info_cards.append({"icon": "help-circle", "label": "Subject", "value": inquiry.subject[:40] if inquiry.subject else ""})

    return JsonResponse({
        "found": True,
        "type": "inquiry",
        "reference": inquiry.reference_number,
        "status": inquiry.status,
        "status_display": sm["label"],
        "progress": sm["progress"],
        "status_color": sm["css"],
        "escalated": bool(inquiry.escalated_at),
        "info_cards": info_cards,
        "timeline": timeline,
        "response": {
            "has_response": bool(inquiry.department_response_en or inquiry.department_response_ar),
            "en": inquiry.department_response_en or "",
            "ar": inquiry.department_response_ar or "",
        },
    })


def _track_observation(reference):
    from apps.observations.models import Observation

    try:
        observation = Observation.objects.select_related("hospital", "category").prefetch_related("status_logs", "notes").get(tracking_code__iexact=reference)
    except Observation.DoesNotExist:
        return JsonResponse({"found": False, "error": "Observation not found"})

    status_progress = {
        "open": 15, "in_progress": 50,
        "resolved": 100, "closed": 100,
    }
    status_css = {
        "open": "amber", "in_progress": "blue",
        "resolved": "emerald", "closed": "slate",
    }

    timeline = []
    if observation.status in ("resolved", "closed") and (observation.department_response_en or observation.department_response_ar):
        timeline.append({
            "type": "response",
            "icon": "check-circle-2",
            "title": "Response Sent",
            "comment": "",
            "created_at": (observation.department_responded_at or observation.updated_at).strftime("%Y-%m-%d %H:%M"),
        })

    info_cards = [
        {"icon": "calendar", "label": "Submitted", "value": observation.created_at.strftime("%b %d, %Y")},
        {"icon": "tag", "label": "Category", "value": observation.category.name if observation.category else "Not specified"},
        {"icon": "activity", "label": "Severity", "value": observation.get_severity_display(), "severity": observation.severity},
    ]

    return JsonResponse({
        "found": True,
        "type": "observation",
        "reference": observation.tracking_code,
        "status": observation.status,
        "status_display": observation.get_status_display(),
        "progress": status_progress.get(observation.status, 15),
        "status_color": status_css.get(observation.status, "slate"),
        "escalated": False,
        "info_cards": info_cards,
        "timeline": timeline,
        "response": {
            "has_response": bool(observation.department_response_en or observation.department_response_ar),
            "en": observation.department_response_en or "",
            "ar": observation.department_response_ar or "",
        },
    })


@require_POST
def public_observation_submit(request):
    """
    Handle public observation submissions.

    Creates an observation from public submission.
    Returns JSON response with tracking code.
    """
    from apps.observations.models import Observation, ObservationAttachment
    from apps.observations.services import ObservationService
    from apps.organizations.models import Hospital, Department, Section, OrgSubSection
    import mimetypes

    hospital_id = request.POST.get("hospital", "").strip()
    severity = request.POST.get("severity", "medium")
    title = request.POST.get("title", "").strip()
    description = request.POST.get("description", "").strip()
    location_text = request.POST.get("location_text", "").strip()
    location_type = request.POST.get("location_type", "").strip()
    area_id = request.POST.get("area", "").strip()
    department_id = request.POST.get("department", "").strip()
    section_id = request.POST.get("section", "").strip()
    incident_datetime = request.POST.get("incident_datetime", "")
    reporter_staff_id = request.POST.get("reporter_staff_id", "").strip()
    reporter_name = request.POST.get("reporter_name", "").strip()
    reporter_phone = request.POST.get("reporter_phone", "").strip()
    reporter_email = request.POST.get("reporter_email", "").strip()

    # Validation
    errors = []

    if not description:
        errors.append("Description is required")
    if not hospital_id:
        errors.append("Hospital selection is required")

    if severity not in ["low", "medium", "high", "critical"]:
        errors.append("Invalid severity selected")

    if errors:
        return JsonResponse({"success": False, "errors": errors}, status=400)

    try:
        hospital = Hospital.objects.get(id=hospital_id)

        department = Department.objects.filter(id=department_id).first() if department_id else None
        section = Section.objects.filter(id=section_id).first() if section_id else None
        from apps.organizations.models import Area
        area = Area.objects.filter(id=area_id).first() if area_id else None

        # Get client info
        def get_client_ip(req):
            x_forwarded_for = req.META.get("HTTP_X_FORWARDED_FOR")
            if x_forwarded_for:
                ip = x_forwarded_for.split(",")[0].strip()
            else:
                ip = req.META.get("REMOTE_ADDR")
            return ip

        client_ip = get_client_ip(request)
        user_agent = request.META.get("HTTP_USER_AGENT", "")

        # Handle file uploads
        attachments = request.FILES.getlist("attachments")

        # Create observation using service
        observation = ObservationService.create_observation(
            description=description,
            severity=severity,
            category=None,
            title=title,
            hospital=hospital,
            location_text=location_text,
            location_type=location_type,
            assigned_department=department,
            section=section,
            area=area,
            incident_datetime=incident_datetime if incident_datetime else None,
            reporter_staff_id=reporter_staff_id,
            reporter_name=reporter_name,
            reporter_phone=reporter_phone,
            reporter_email=reporter_email,
            client_ip=client_ip,
            user_agent=user_agent,
            attachments=attachments,
        )

        return JsonResponse(
            {"success": True, "tracking_code": observation.tracking_code, "observation_id": str(observation.id)}
        )
    except Exception as e:
        return JsonResponse({"success": False, "errors": [str(e)]}, status=500)


@login_required
@require_http_methods(["POST"])
@login_required
@require_http_methods(["POST"])
def add_note(request):
    from django.contrib.contenttypes.models import ContentType
    from apps.core.models import Note

    content_type_id = request.POST.get("content_type_id")
    object_id = request.POST.get("object_id")
    note_text = request.POST.get("note", "").strip()

    if not note_text:
        messages.error(request, _("Note cannot be empty."))
        return redirect(request.META.get("HTTP_REFERER", "/"))

    try:
        ct = ContentType.objects.get(pk=content_type_id)
        obj = ct.get_object_for_this_type(pk=object_id)
    except Exception:
        messages.error(request, _("Invalid object reference."))
        return redirect(request.META.get("HTTP_REFERER", "/"))

    Note.objects.create(
        content_type=ct,
        object_id=object_id,
        note=note_text,
        created_by=request.user,
        is_internal=True,
    )
    messages.success(request, _("Note added successfully."))
    return redirect(request.META.get("HTTP_REFERER", "/"))


@require_POST
@csrf_exempt
def public_set_satisfaction(request):
    """Public endpoint to set patient satisfaction for a complaint (no auth required)."""
    from django.utils import timezone
    from apps.complaints.models import Complaint

    reference = request.POST.get("reference", "").strip()
    satisfaction = request.POST.get("satisfaction", "").strip()

    if not reference or not satisfaction:
        return JsonResponse({"success": False, "error": "Reference and satisfaction are required."}, status=400)

    valid_choices = ["satisfied", "neutral", "dissatisfied"]
    if satisfaction not in valid_choices:
        return JsonResponse({"success": False, "error": "Invalid satisfaction value."}, status=400)

    try:
        complaint = Complaint.objects.get(reference_number__iexact=reference)
    except Complaint.DoesNotExist:
        return JsonResponse({"success": False, "error": "Complaint not found."}, status=404)

    if complaint.status not in ("resolved", "closed") or not complaint.resolution:
        return JsonResponse({"success": False, "error": "Satisfaction can only be set for resolved complaints."}, status=400)

    complaint.satisfaction = satisfaction
    complaint.satisfaction_set_at = timezone.now()
    complaint.save(update_fields=["satisfaction", "satisfaction_set_at", "updated_at"])

    return JsonResponse({"success": True, "satisfaction": complaint.satisfaction})
