from __future__ import annotations

from typing import Any

import requests

from core.logging import LocalLogging
from utils.urls_utils import UrlsUtils


class GrafanaClient:
    DEFAULT_TIMEOUT_SECONDS = 30

    def __init__(self, base_url: str, token: str | None = None, username: str | None = None, password: str | None = None, timeout_seconds: int = DEFAULT_TIMEOUT_SECONDS) -> None:
        self.logger = LocalLogging.get_logger("hape.grafana_client")
        self.base_url = UrlsUtils.normalize_grafana_base_url(base_url)
        self.timeout_seconds = timeout_seconds
        self.session = requests.Session()
        self.session.headers.update(self._build_headers(token=token))
        self.session.auth = self._build_auth(username=username, password=password)

    @staticmethod
    def _build_headers(token: str | None) -> dict[str, str]:
        headers = {"Accept": "application/json"}
        if token:
            headers["Authorization"] = f"Bearer {token}"
        return headers

    @staticmethod
    def _build_auth(username: str | None, password: str | None) -> tuple[str, str] | None:
        if username is None and password is None:
            return None
        if username is None or password is None:
            raise ValueError("Both Grafana username and password are required for basic auth.")
        return username, password

    def _request_json(self, path: str, params: dict[str, Any] | None = None) -> Any:
        url = f"{self.base_url}{path}"
        self.logger.debug(f"_request_json(path: {path}, params: {params})")
        response = self.session.get(url, params=params, timeout=self.timeout_seconds)
        response.raise_for_status()
        if not response.content:
            return None
        return response.json()

    def list_datasources(self) -> list[dict[str, Any]]:
        self.logger.debug("list_datasources()")
        data = self._request_json("/api/datasources")
        if isinstance(data, list):
            return data
        return []

    def list_dashboards(self) -> list[dict[str, Any]]:
        self.logger.debug("list_dashboards()")
        page = 1
        all_dashboards: list[dict[str, Any]] = []
        while True:
            data = self._request_json("/api/search", params={"type": "dash-db", "limit": 5000, "page": page})
            if not data:
                break
            if not isinstance(data, list):
                break
            all_dashboards.extend(data)
            page += 1
        return all_dashboards

    def get_dashboard_by_uid(self, uid: str) -> dict[str, Any]:
        self.logger.debug(f"get_dashboard_by_uid(uid: {uid})")
        data = self._request_json(f"/api/dashboards/uid/{uid}")
        if isinstance(data, dict):
            return data
        return {}

if __name__ == "__main__":
    
    grafana_client = GrafanaClient(
        base_url="http://127.0.0.1:51716",
        token="",
        username="user",
        password="password",
    )
    grafana_datasources = grafana_client.list_dashboards()
    print(len(grafana_datasources))
