"""Statusuebersicht -- die Startseite.

Bewusst auch ohne Anmeldung erreichbar (abschaltbar ueber die Einstellung
``dashboard_public``): sie ist ein Informationsboard fuer jeden im Netz, damit
niemand sich anmelden muss, um zu sehen, ob ein Geraet laeuft.

Ohne Anmeldung zeigt sie **nur** Name und Erreichbarkeit aktiver Geraete. Keine
IP-Adressen, keine MAC, keine Switch-/Portzuordnung, keine Zaehler zu
deaktivierten Geraeten -- der Vorgaenger gab hier deutlich mehr heraus, als ein
oeffentliches Board hergeben sollte.
"""

from __future__ import annotations

from typing import Any

from flask import Blueprint, abort, render_template, request
from tesm_core.extension import core, db

from ..services import monitor

bp = Blueprint("dashboard", __name__)


def _maintenance_active() -> bool:
    from tesm_core.extension import core

    manager = core().license
    return manager is None or manager.module_active("maintenance")


def _public_allowed() -> bool:
    return bool(core().settings.get(db(), "dashboard_public"))


def _tiles(*, authenticated: bool) -> dict[str, Any]:
    from tesm_core.auth.models import current_user

    from ..services import inventory, restart

    conn = db()
    counts = monitor.dashboard_counts(conn)
    rows = inventory.list_devices(conn, only_active=not authenticated)

    detailed = authenticated and current_user.has("devices.view")
    tiles: list[dict[str, Any]] = []
    for row in rows:
        entry: dict[str, Any] = {
            "id": int(row["id"]),
            "name": str(row["name"]),
            "state": "disabled" if not row["is_active"] else str(row["state"]),
            "last_change_at": row["last_change_at"],
            "category": str(row["category"] or ""),
            "location": str(row["location"] or ""),
        }
        if detailed:
            entry.update(
                {
                    "ip": str(row["ip"]),
                    "mac": str(row["mac"]),
                    "switch": str(row["switch_hostname"] or ""),
                    "port": str(row["port"] or ""),
                    "latency_ms": row["latency_ms"],
                    "last_check_at": row["last_check_at"],
                    "restart_count": row["restart_count"] or 0,
                    "credential_category": str(row["credential_category"] or ""),
                    # Nicht nur PoE: ein Geraet kann auch ueber SSH oder RPC
                    # neu startbar sein. Die Kachel zeigt den bevorzugten Weg.
                    "restart_methods": restart.available(
                        row, maintenance_active=_maintenance_active()
                    ),
                }
            )
        tiles.append(entry)

    sections = [
        {
            # Vor "nicht erreichbar": ein Geraet, das gerade neu startet, ist
            # erwartbar weg. Wer die Uebersicht ansieht, will genau das zuerst
            # wissen -- sonst haelt er einen laufenden Neustart fuer einen Ausfall.
            "key": "restarting",
            "label": "Neustart laeuft",
            "kind": "warning",
            "tiles": [tile for tile in tiles if tile["state"] == "restarting"],
        },
        {
            "key": "offline",
            "label": "Nicht erreichbar",
            "kind": "danger",
            "tiles": [tile for tile in tiles if tile["state"] == "offline"],
        },
        {
            "key": "online",
            "label": "Erreichbar",
            "kind": "ok",
            "tiles": [tile for tile in tiles if tile["state"] == "online"],
        },
        {
            "key": "unknown",
            "label": "Noch nicht geprueft",
            "kind": "warning",
            "tiles": [tile for tile in tiles if tile["state"] == "unknown"],
        },
    ]
    if authenticated:
        sections.append(
            {
                "key": "disabled",
                "label": "Deaktiviert",
                "kind": "muted",
                "tiles": [tile for tile in tiles if tile["state"] == "disabled"],
            }
        )

    return {
        "counts": counts,
        "sections": sections,
        "detailed": detailed,
        "interval": int(core().settings.get(conn, "monitor_interval_seconds") or 300),
    }


@bp.get("/uebersicht")
def index():
    from tesm_core.auth.models import current_user

    if not current_user.is_authenticated and not _public_allowed():
        from flask import redirect, url_for

        return redirect(url_for("auth.login"))
    data = _tiles(authenticated=bool(current_user.is_authenticated))
    return render_template("tesm/dashboard.html", **data)


def index_view():
    """Wird als Endpunkt ``index`` registriert (Startseite)."""
    return index()


@bp.get("/uebersicht/kacheln")
def tiles():
    """Teilbereich fuer die automatische Aktualisierung -- liefert nur HTML-Fragment."""
    from tesm_core.auth.models import current_user

    if not current_user.is_authenticated and not _public_allowed():
        abort(404)
    data = _tiles(authenticated=bool(current_user.is_authenticated))
    return render_template("tesm/_dashboard_tiles.html", **data)
