"""Grafana dashboard generator for gaol container metrics."""

from __future__ import annotations

import json
import uuid
from typing import Any


class GrafanaDashboardGenerator:
    """Generates Grafana dashboard JSON for gaol container metrics.

    Creates a comprehensive dashboard with panels for CPU, memory,
    network I/O, block I/O, and container information.

    Example:
        >>> generator = GrafanaDashboardGenerator()
        >>> dashboard_json = generator.generate()
        >>> print(dashboard_json)
    """

    def __init__(
        self,
        title: str = "Gaol Container Metrics",
        datasource: str = "prometheus",
        refresh: str = "10s",
    ) -> None:
        """Initialize the dashboard generator.

        Args:
            title: Dashboard title
            datasource: Prometheus datasource name in Grafana
            refresh: Auto-refresh interval
        """
        self.title = title
        self.datasource = datasource
        self.refresh = refresh
        self._uid = str(uuid.uuid4())[:8]

    def generate(self) -> str:
        """Generate the complete dashboard JSON.

        Returns:
            JSON string of the Grafana dashboard
        """
        dashboard = self._build_dashboard()
        return json.dumps(dashboard, indent=2)

    def generate_dict(self) -> dict[str, Any]:
        """Generate the dashboard as a dictionary.

        Returns:
            Dashboard definition as a dictionary
        """
        return self._build_dashboard()

    def _build_dashboard(self) -> dict[str, Any]:
        """Build the complete dashboard structure."""
        return {
            "annotations": {"list": []},
            "editable": True,
            "fiscalYearStartMonth": 0,
            "graphTooltip": 1,  # Shared crosshair
            "id": None,
            "links": [],
            "panels": self._build_panels(),
            "refresh": self.refresh,
            "schemaVersion": 39,
            "tags": ["gaol", "containers"],
            "templating": {"list": self._build_variables()},
            "time": {"from": "now-1h", "to": "now"},
            "timepicker": {},
            "timezone": "browser",
            "title": self.title,
            "uid": self._uid,
            "version": 1,
        }

    def _build_variables(self) -> list[dict[str, Any]]:
        """Build template variables for filtering."""
        return [
            {
                "current": {"selected": True, "text": "All", "value": "$__all"},
                "datasource": {"type": "prometheus", "uid": self.datasource},
                "definition": 'label_values(gaol_container_info, container_name)',
                "includeAll": True,
                "label": "Container",
                "multi": True,
                "name": "container",
                "options": [],
                "query": {
                    "query": 'label_values(gaol_container_info, container_name)',
                    "refId": "StandardVariableQuery",
                },
                "refresh": 2,
                "regex": "",
                "skipUrlSync": False,
                "sort": 1,
                "type": "query",
            },
            {
                "current": {"selected": True, "text": "All", "value": "$__all"},
                "datasource": {"type": "prometheus", "uid": self.datasource},
                "definition": 'label_values(gaol_container_info, runtime)',
                "includeAll": True,
                "label": "Runtime",
                "multi": True,
                "name": "runtime",
                "options": [],
                "query": {
                    "query": 'label_values(gaol_container_info, runtime)',
                    "refId": "StandardVariableQuery",
                },
                "refresh": 2,
                "regex": "",
                "skipUrlSync": False,
                "sort": 1,
                "type": "query",
            },
        ]

    def _build_panels(self) -> list[dict[str, Any]]:
        """Build all dashboard panels."""
        panels = []
        y_pos = 0
        panel_id = 1

        # Row: Overview
        panels.append(self._build_row("Overview", y_pos))
        y_pos += 1
        panel_id += 1

        # Container count stat
        panels.append(self._build_stat_panel(
            id=panel_id,
            title="Running Containers",
            expr='count(gaol_container_info{container_name=~"$container", runtime=~"$runtime", status="running"})',
            x=0, y=y_pos, w=6, h=4,
        ))
        panel_id += 1

        # Total CPU usage stat
        panels.append(self._build_stat_panel(
            id=panel_id,
            title="Total CPU Usage",
            expr='sum(gaol_container_cpu_percent{container_name=~"$container", runtime=~"$runtime"})',
            unit="percent",
            x=6, y=y_pos, w=6, h=4,
        ))
        panel_id += 1

        # Total memory usage stat
        panels.append(self._build_stat_panel(
            id=panel_id,
            title="Total Memory Usage",
            expr='sum(gaol_container_memory_bytes{container_name=~"$container", runtime=~"$runtime"})',
            unit="bytes",
            x=12, y=y_pos, w=6, h=4,
        ))
        panel_id += 1

        # Total PIDs stat
        panels.append(self._build_stat_panel(
            id=panel_id,
            title="Total Processes",
            expr='sum(gaol_container_pids{container_name=~"$container", runtime=~"$runtime"})',
            x=18, y=y_pos, w=6, h=4,
        ))
        panel_id += 1
        y_pos += 4

        # Row: CPU & Memory
        panels.append(self._build_row("CPU & Memory", y_pos))
        y_pos += 1
        panel_id += 1

        # CPU usage graph
        panels.append(self._build_timeseries_panel(
            id=panel_id,
            title="CPU Usage",
            expr='gaol_container_cpu_percent{container_name=~"$container", runtime=~"$runtime"}',
            legend="{{container_name}}",
            unit="percent",
            x=0, y=y_pos, w=12, h=8,
        ))
        panel_id += 1

        # Memory usage graph
        panels.append(self._build_timeseries_panel(
            id=panel_id,
            title="Memory Usage",
            expr='gaol_container_memory_bytes{container_name=~"$container", runtime=~"$runtime"}',
            legend="{{container_name}}",
            unit="bytes",
            x=12, y=y_pos, w=12, h=8,
        ))
        panel_id += 1
        y_pos += 8

        # Memory percent graph
        panels.append(self._build_timeseries_panel(
            id=panel_id,
            title="Memory Usage %",
            expr='gaol_container_memory_percent{container_name=~"$container", runtime=~"$runtime"}',
            legend="{{container_name}}",
            unit="percent",
            x=0, y=y_pos, w=12, h=8,
        ))
        panel_id += 1

        # PIDs graph
        panels.append(self._build_timeseries_panel(
            id=panel_id,
            title="Process Count",
            expr='gaol_container_pids{container_name=~"$container", runtime=~"$runtime"}',
            legend="{{container_name}}",
            unit="short",
            x=12, y=y_pos, w=12, h=8,
        ))
        panel_id += 1
        y_pos += 8

        # Row: Network I/O
        panels.append(self._build_row("Network I/O", y_pos))
        y_pos += 1
        panel_id += 1

        # Network RX graph
        panels.append(self._build_timeseries_panel(
            id=panel_id,
            title="Network Received",
            expr='rate(gaol_container_network_rx_bytes{container_name=~"$container", runtime=~"$runtime"}[1m])',
            legend="{{container_name}}",
            unit="Bps",
            x=0, y=y_pos, w=12, h=8,
        ))
        panel_id += 1

        # Network TX graph
        panels.append(self._build_timeseries_panel(
            id=panel_id,
            title="Network Transmitted",
            expr='rate(gaol_container_network_tx_bytes{container_name=~"$container", runtime=~"$runtime"}[1m])',
            legend="{{container_name}}",
            unit="Bps",
            x=12, y=y_pos, w=12, h=8,
        ))
        panel_id += 1
        y_pos += 8

        # Row: Block I/O
        panels.append(self._build_row("Block I/O", y_pos))
        y_pos += 1
        panel_id += 1

        # Block read graph
        panels.append(self._build_timeseries_panel(
            id=panel_id,
            title="Block Read",
            expr='rate(gaol_container_block_read_bytes{container_name=~"$container", runtime=~"$runtime"}[1m])',
            legend="{{container_name}}",
            unit="Bps",
            x=0, y=y_pos, w=12, h=8,
        ))
        panel_id += 1

        # Block write graph
        panels.append(self._build_timeseries_panel(
            id=panel_id,
            title="Block Write",
            expr='rate(gaol_container_block_write_bytes{container_name=~"$container", runtime=~"$runtime"}[1m])',
            legend="{{container_name}}",
            unit="Bps",
            x=12, y=y_pos, w=12, h=8,
        ))
        panel_id += 1
        y_pos += 8

        # Row: Container Info
        panels.append(self._build_row("Container Info", y_pos))
        y_pos += 1
        panel_id += 1

        # Container table
        panels.append(self._build_table_panel(
            id=panel_id,
            title="Container Details",
            x=0, y=y_pos, w=24, h=8,
        ))

        return panels

    def _build_row(self, title: str, y: int) -> dict[str, Any]:
        """Build a collapsible row panel."""
        return {
            "collapsed": False,
            "gridPos": {"h": 1, "w": 24, "x": 0, "y": y},
            "id": None,
            "panels": [],
            "title": title,
            "type": "row",
        }

    def _build_stat_panel(
        self,
        id: int,
        title: str,
        expr: str,
        unit: str = "short",
        x: int = 0,
        y: int = 0,
        w: int = 6,
        h: int = 4,
    ) -> dict[str, Any]:
        """Build a stat panel."""
        return {
            "datasource": {"type": "prometheus", "uid": self.datasource},
            "fieldConfig": {
                "defaults": {
                    "color": {"mode": "thresholds"},
                    "mappings": [],
                    "thresholds": {
                        "mode": "absolute",
                        "steps": [
                            {"color": "green", "value": None},
                        ],
                    },
                    "unit": unit,
                },
                "overrides": [],
            },
            "gridPos": {"h": h, "w": w, "x": x, "y": y},
            "id": id,
            "options": {
                "colorMode": "value",
                "graphMode": "area",
                "justifyMode": "auto",
                "orientation": "auto",
                "reduceOptions": {
                    "calcs": ["lastNotNull"],
                    "fields": "",
                    "values": False,
                },
                "textMode": "auto",
            },
            "pluginVersion": "10.0.0",
            "targets": [
                {
                    "datasource": {"type": "prometheus", "uid": self.datasource},
                    "expr": expr,
                    "refId": "A",
                }
            ],
            "title": title,
            "type": "stat",
        }

    def _build_timeseries_panel(
        self,
        id: int,
        title: str,
        expr: str,
        legend: str,
        unit: str = "short",
        x: int = 0,
        y: int = 0,
        w: int = 12,
        h: int = 8,
    ) -> dict[str, Any]:
        """Build a time series graph panel."""
        return {
            "datasource": {"type": "prometheus", "uid": self.datasource},
            "fieldConfig": {
                "defaults": {
                    "color": {"mode": "palette-classic"},
                    "custom": {
                        "axisBorderShow": False,
                        "axisCenteredZero": False,
                        "axisColorMode": "text",
                        "axisLabel": "",
                        "axisPlacement": "auto",
                        "barAlignment": 0,
                        "drawStyle": "line",
                        "fillOpacity": 10,
                        "gradientMode": "none",
                        "hideFrom": {"legend": False, "tooltip": False, "viz": False},
                        "lineInterpolation": "linear",
                        "lineWidth": 1,
                        "pointSize": 5,
                        "scaleDistribution": {"type": "linear"},
                        "showPoints": "never",
                        "spanNulls": False,
                        "stacking": {"group": "A", "mode": "none"},
                        "thresholdsStyle": {"mode": "off"},
                    },
                    "mappings": [],
                    "thresholds": {
                        "mode": "absolute",
                        "steps": [{"color": "green", "value": None}],
                    },
                    "unit": unit,
                },
                "overrides": [],
            },
            "gridPos": {"h": h, "w": w, "x": x, "y": y},
            "id": id,
            "options": {
                "legend": {"calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": True},
                "tooltip": {"mode": "multi", "sort": "none"},
            },
            "targets": [
                {
                    "datasource": {"type": "prometheus", "uid": self.datasource},
                    "expr": expr,
                    "legendFormat": legend,
                    "refId": "A",
                }
            ],
            "title": title,
            "type": "timeseries",
        }

    def _build_table_panel(
        self,
        id: int,
        title: str,
        x: int = 0,
        y: int = 0,
        w: int = 24,
        h: int = 8,
    ) -> dict[str, Any]:
        """Build a table panel showing container info."""
        return {
            "datasource": {"type": "prometheus", "uid": self.datasource},
            "fieldConfig": {
                "defaults": {
                    "color": {"mode": "thresholds"},
                    "mappings": [],
                    "thresholds": {
                        "mode": "absolute",
                        "steps": [{"color": "green", "value": None}],
                    },
                },
                "overrides": [
                    {
                        "matcher": {"id": "byName", "options": "container_name"},
                        "properties": [{"id": "displayName", "value": "Container"}],
                    },
                    {
                        "matcher": {"id": "byName", "options": "runtime"},
                        "properties": [{"id": "displayName", "value": "Runtime"}],
                    },
                    {
                        "matcher": {"id": "byName", "options": "status"},
                        "properties": [{"id": "displayName", "value": "Status"}],
                    },
                    {
                        "matcher": {"id": "byName", "options": "distro"},
                        "properties": [{"id": "displayName", "value": "Distro"}],
                    },
                    {
                        "matcher": {"id": "byName", "options": "profile"},
                        "properties": [{"id": "displayName", "value": "Profile"}],
                    },
                ],
            },
            "gridPos": {"h": h, "w": w, "x": x, "y": y},
            "id": id,
            "options": {
                "cellHeight": "sm",
                "footer": {"countRows": False, "fields": "", "reducer": ["sum"], "show": False},
                "showHeader": True,
            },
            "pluginVersion": "10.0.0",
            "targets": [
                {
                    "datasource": {"type": "prometheus", "uid": self.datasource},
                    "expr": 'gaol_container_info{container_name=~"$container", runtime=~"$runtime"}',
                    "format": "table",
                    "instant": True,
                    "refId": "A",
                }
            ],
            "title": title,
            "transformations": [
                {"id": "labelsToFields", "options": {}},
                {
                    "id": "organize",
                    "options": {
                        "excludeByName": {"Time": True, "Value": True, "__name__": True},
                        "indexByName": {},
                        "renameByName": {},
                    },
                },
            ],
            "type": "table",
        }


def generate_grafana_dashboard(
    title: str = "Gaol Container Metrics",
    datasource: str = "prometheus",
) -> str:
    """Generate a Grafana dashboard JSON.

    Args:
        title: Dashboard title
        datasource: Prometheus datasource name

    Returns:
        JSON string of the dashboard
    """
    generator = GrafanaDashboardGenerator(title=title, datasource=datasource)
    return generator.generate()
