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

from django.contrib.auth.decorators import login_required
from django.db import connection
from django.http import JsonResponse
from django.shortcuts import redirect, render
from django.views.decorators.cache import never_cache
from django.views.decorators.http import require_GET, require_POST


@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, Location, MainSection, SubSection
    import uuid

    # Get form data
    name = request.POST.get("name", "").strip()
    email = request.POST.get("email", "").strip()
    phone = request.POST.get("phone", "").strip()
    hospital_id = request.POST.get("hospital")
    category = request.POST.get("category", "").strip()
    subject = request.POST.get("subject", "").strip()
    message = request.POST.get("message", "").strip()
    location_id = request.POST.get("location", "").strip()
    main_section_id = request.POST.get("main_section", "").strip()
    subsection_id = request.POST.get("subsection", "").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)

        location = Location.objects.filter(id=location_id).first() if location_id else None
        main_section = MainSection.objects.filter(id=main_section_id).first() if main_section_id else None
        subsection = SubSection.objects.filter(id=subsection_id).first() if subsection_id else None

        # Create inquiry (using correct field names from model)
        inquiry = Inquiry.objects.create(
            hospital=hospital,
            contact_name=name,
            contact_email=email,
            contact_phone=phone,
            subject=subject,
            message=message,
            category=category,
            status="open",
            location=location,
            main_section=main_section,
            subsection=subsection,
        )

        reference_number = f"INQ-{str(inquiry.id)[:8].upper()}"
        inquiry.reference_number = reference_number
        inquiry.save(update_fields=["reference_number"])

        try:
            from apps.complaints.tasks import analyze_inquiry_with_ai
            analyze_inquiry_with_ai.delay(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

            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=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 type (complaint/inquiry/observation) and reference parameters.
    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 track_type or not reference:
        return JsonResponse({"found": False, "error": str(_("Type and reference are required."))}, 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

    try:
        complaint = (
            Complaint.objects.select_related("hospital", "department", "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", "communication"])
        .order_by("-created_at")[:20]
    )

    timeline = []
    for u in public_updates:
        icon = "refresh-cw" if u.update_type == "status_change" else ("check-circle-2" if u.update_type == "resolution" else "message-square")
        title = "Status Updated" if u.update_type == "status_change" else ("Final Resolution" if u.update_type == "resolution" else "Update Received")
        timeline.append({
            "type": u.update_type,
            "icon": icon,
            "title": title,
            "comment": u.comments or "",
            "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"})

    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,
    })


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

    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"},
        "contacted": {"label": "In Progress", "progress": 50, "css": "blue"},
        "contacted_no_response": {"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"})

    updates = InquiryUpdate.objects.filter(inquiry=inquiry).select_related("created_by").order_by("-created_at")[:20]

    timeline = []
    for u in updates:
        icon = "refresh-cw" if u.update_type == "status_change" else ("check-circle-2" if u.update_type == "response" else "message-square")
        title = "Status Updated" if u.update_type == "status_change" else ("Response Received" if u.update_type == "response" else "Update Received")
        timeline.append({
            "type": u.update_type,
            "icon": icon,
            "title": title,
            "comment": u.message or "",
            "created_at": u.created_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,
    })


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

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

    status_progress = {
        "new": 15, "triaged": 30, "assigned": 40, "in_progress": 50,
        "resolved": 100, "closed": 100, "rejected": 0, "duplicate": 0,
    }
    status_css = {
        "new": "sky", "triaged": "teal", "assigned": "teal", "in_progress": "blue",
        "resolved": "emerald", "closed": "slate", "rejected": "rose", "duplicate": "slate",
    }

    timeline = []
    if hasattr(observation, 'public_timeline') and callable(observation.public_timeline):
        for item in observation.public_timeline:
            icon = "refresh-cw" if item.get("type") == "status_change" else ("message-square" if item.get("type") == "note" else "check-circle-2")
            timeline.append({
                "type": item.get("type", "note"),
                "icon": icon,
                "title": "Status Updated" if item.get("type") == "status_change" else ("Update Received" if item.get("type") == "note" else "Final Resolution"),
                "comment": item.get("comment", ""),
                "created_at": item.get("created_at", ""),
            })

    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,
    })


@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, ObservationCategory
    from django.shortcuts import get_object_or_404
    from apps.observations.services import ObservationService
    from apps.organizations.models import Hospital, Location, MainSection, SubSection
    import mimetypes

    # Get form data
    hospital_id = request.POST.get("hospital", "").strip()
    category_id = request.POST.get("category")
    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_id = request.POST.get("location", "").strip()
    main_section_id = request.POST.get("main_section", "").strip()
    subsection_id = request.POST.get("subsection", "").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)
        category = None
        if category_id:
            category = get_object_or_404(ObservationCategory, id=category_id)

        location = Location.objects.filter(id=location_id).first() if location_id else None
        main_section = MainSection.objects.filter(id=main_section_id).first() if main_section_id else None
        subsection = SubSection.objects.filter(id=subsection_id).first() if subsection_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=category,
            title=title,
            hospital=hospital,
            location_text=location_text,
            location=location,
            main_section=main_section,
            subsection=subsection,
            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)
