"""Prometheus service definition."""

from __future__ import annotations

from typing import TYPE_CHECKING, Any

import requests

from media_library_viewer_api.integrations.base import (
    SecretField,
    ServiceBaseUrl,
    ServiceConfigBase,
    ServiceDefinition,
    TestResult,
    WidgetConfigBase,
    translate_connection_error,
    widget_kind,
)

if TYPE_CHECKING:
    from media_library_viewer_api.services.settings_store import SettingsStore


def test_connection(
    config: dict[str, Any],
    secrets: dict[str, str],
    store: SettingsStore,
) -> TestResult:
    """POST {grafana_url}/api/ds/query with expr 'up' via the Grafana gateway."""
    try:
        grafana_url = str(config.get("grafana_url") or "").rstrip("/")
        api_key = str(secrets.get("grafana_api_key") or "")
        datasource_uid = str(config.get("datasource_uid") or "prometheus")
        timeout = int(config.get("timeout_seconds") or 10)
        if not grafana_url:
            return TestResult(ok=False, detail="Grafana gateway URL is required.")
        if not api_key:
            return TestResult(ok=False, detail="Grafana API key is required.")
        body = {
            "queries": [
                {
                    "datasource": {"uid": datasource_uid, "type": "prometheus"},
                    "expr": "up",
                    "format": "time_series",
                    "intervalMs": 15000,
                    "maxDataPoints": 1,
                    "refId": "A",
                }
            ],
            "from": "now-1m",
            "to": "now",
        }
        resp = requests.post(
            f"{grafana_url}/api/ds/query",
            json=body,
            timeout=timeout,
            headers={"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"},
        )
        resp.raise_for_status()
        return TestResult(
            ok=True,
            detail="Grafana gateway reachable.",
            evidence="Gateway reachable; datasource responded.",
        )
    except requests.HTTPError as exc:
        return translate_connection_error(exc, context="Prometheus via Grafana")
    except Exception as exc:
        return translate_connection_error(exc, context="Prometheus via Grafana")


class PrometheusConfig(ServiceConfigBase):
    """Non-secret Prometheus-via-Grafana gateway config."""

    grafana_url: ServiceBaseUrl
    datasource_uid: str = "prometheus"
    timeout_seconds: int = 10


class PrometheusMetricWidgetConfig(WidgetConfigBase):
    """A PromQL instant query rendered as a metric."""

    promql: str


class PrometheusChartWidgetConfig(WidgetConfigBase):
    """A PromQL range query rendered as a multi-series line chart (SC-101..SC-104)."""

    promql: str
    window: str = "1h"  # one of 1h / 6h / 24h / 7d (see WINDOW_PRESETS)


class PrometheusGaugeWidgetConfig(WidgetConfigBase):
    """A PromQL instant query rendered as a gauge with optional threshold bands (SC-109..SC-111)."""

    promql: str
    warn_at: float | None = None
    crit_at: float | None = None
    min: float | None = None
    max: float | None = None
    unit: str | None = None


class PrometheusMeanWidgetConfig(WidgetConfigBase):
    """A PromQL range query averaged client-side into a single value (SC-112..SC-114)."""

    promql: str
    window: str = "1h"  # one of 1h / 6h / 24h / 7d (see WINDOW_PRESETS)
    unit: str | None = None


DEFINITION = ServiceDefinition(
    service_type="prometheus",
    name="Prometheus",
    description="Metrics storage and PromQL queries.",
    config_model=PrometheusConfig,
    secret_fields=[
        SecretField(
            key="grafana_api_key",
            label="Grafana API key",
            required=True,
            helper="Service account token or API key for the Grafana gateway",
        ),
    ],
    widget_kinds=[
        widget_kind(
            kind="metric",
            name="Metric",
            description="Instant query result rendered as a metric.",
            model_cls=PrometheusMetricWidgetConfig,
            default_config={"promql": ""},
            refresh_interval_ms=30_000,
        ),
        widget_kind(
            kind="chart",
            name="Chart",
            description="Multi-series line chart from a PromQL range query.",
            model_cls=PrometheusChartWidgetConfig,
            default_config={"promql": "", "window": "1h"},
            refresh_interval_ms=60_000,
        ),
        widget_kind(
            kind="gauge",
            name="Gauge",
            description="Instant query rendered as a gauge with optional threshold bands.",
            model_cls=PrometheusGaugeWidgetConfig,
            default_config={"promql": ""},
            refresh_interval_ms=30_000,
        ),
        widget_kind(
            kind="mean",
            name="Mean",
            description="Average value of a PromQL query over a time window.",
            model_cls=PrometheusMeanWidgetConfig,
            default_config={"promql": "", "window": "1h"},
            refresh_interval_ms=60_000,
        ),
    ],
    test_callable=test_connection,
)
