from datetime import timedelta

from django.contrib import admin, messages
from django.contrib.admin.views.decorators import staff_member_required
from django.db.models import Avg, Count, Q
from django.http import JsonResponse
from django.shortcuts import get_object_or_404, redirect, render
from django.utils import timezone
from django.views.decorators.http import require_POST

from .models import MonitorCheck, MonitorIncident, WebsiteMonitor
from .services import run_due_monitors, run_monitor_check


@staff_member_required
def monitoring_center(request):
    now = timezone.now()
    last_24h = now - timedelta(hours=24)
    monitors = WebsiteMonitor.objects.select_related(
        "technical_asset__service__client"
    ).order_by("status", "name")
    recent_checks = MonitorCheck.objects.select_related("monitor").order_by("-checked_at")[:12]
    open_incidents = MonitorIncident.objects.select_related(
        "monitor__technical_asset__service__client", "internal_task"
    ).filter(status__in=[MonitorIncident.Status.OPEN, MonitorIncident.Status.ACKNOWLEDGED]).order_by("-severity", "-opened_at")[:10]
    last_checks = MonitorCheck.objects.filter(checked_at__gte=last_24h).exclude(result=MonitorCheck.Result.SKIPPED)
    total_checks = last_checks.count()
    successful_checks = last_checks.filter(result__in=[MonitorCheck.Result.UP, MonitorCheck.Result.DEGRADED]).count()
    average_response = last_checks.exclude(response_time_ms__isnull=True).aggregate(value=Avg("response_time_ms"))["value"]
    status_counts = {row["status"]: row["count"] for row in monitors.values("status").annotate(count=Count("id"))}
    context = {
        **admin.site.each_context(request),
        "title": "Centro de monitorização",
        "monitors": monitors[:20],
        "open_incidents": open_incidents,
        "recent_checks": recent_checks,
        "counts": {
            "total": monitors.count(),
            "up": status_counts.get(WebsiteMonitor.Status.UP, 0),
            "degraded": status_counts.get(WebsiteMonitor.Status.DEGRADED, 0),
            "down": status_counts.get(WebsiteMonitor.Status.DOWN, 0),
            "incidents": MonitorIncident.objects.filter(status__in=[MonitorIncident.Status.OPEN, MonitorIncident.Status.ACKNOWLEDGED]).count(),
        },
        "uptime_24h": round((successful_checks / total_checks) * 100, 2) if total_checks else None,
        "average_response": round(average_response or 0),
        "checked_at": now,
    }
    return render(request, "admin/monitoring/center.html", context)


@staff_member_required
@require_POST
def monitoring_run(request):
    monitor_id = request.POST.get("monitor_id")
    try:
        if monitor_id:
            monitor = get_object_or_404(WebsiteMonitor, pk=monitor_id)
            check = run_monitor_check(monitor, triggered_by=request.user)
            return JsonResponse({
                "ok": True,
                "monitor_id": monitor.pk,
                "status": monitor.status,
                "status_label": monitor.get_status_display(),
                "result": check.result,
                "result_label": check.get_result_display(),
                "http_status": check.http_status,
                "response_time_ms": check.response_time_ms,
                "checked_at": check.checked_at.isoformat(),
                "error": check.error_message,
            })
        result = run_due_monitors()
        return JsonResponse({"ok": True, **result})
    except Exception as exc:
        return JsonResponse({"ok": False, "error": str(exc)}, status=500)
