"""Prometheus metrics exporter for NEUROVAULT v0.3."""

from __future__ import annotations

import time
from typing import Any


class PrometheusExporter:
    """Export NEUROVAULT runtime metrics in Prometheus text format."""

    def __init__(self, engine):
        self._engine = engine
        self._start_time = time.time()

    def generate_metrics(self) -> str:
        """Render current metrics snapshot in Prometheus exposition format."""
        stats = self._engine.stats()
        lines = [
            "# HELP neurovault_memories_total Total memories stored",
            "# TYPE neurovault_memories_total gauge",
            f"neurovault_memories_total {stats.get('memory_count', 0)}",
            "",
            "# HELP neurovault_entities_total Total entities in knowledge graph",
            "# TYPE neurovault_entities_total gauge",
            f"neurovault_entities_total {stats.get('entity_count', 0)}",
            "",
            "# HELP neurovault_relationships_total Total relationships",
            "# TYPE neurovault_relationships_total gauge",
            f"neurovault_relationships_total {stats.get('relationship_count', 0)}",
            "",
            "# HELP neurovault_clusters_total Total clusters",
            "# TYPE neurovault_clusters_total gauge",
            f"neurovault_clusters_total {stats.get('cluster_count', 0)}",
            "",
            "# HELP neurovault_insights_total Total insights generated",
            "# TYPE neurovault_insights_total gauge",
            f"neurovault_insights_total {stats.get('insight_count', 0)}",
            "",
            "# HELP neurovault_uptime_seconds Daemon uptime",
            "# TYPE neurovault_uptime_seconds gauge",
            f"neurovault_uptime_seconds {time.time() - self._start_time:.0f}",
            "",
            "# HELP neurovault_plugins_total Total plugin count",
            "# TYPE neurovault_plugins_total gauge",
            f"neurovault_plugins_total {stats.get('plugin_count', 0)}",
            "",
            "# HELP neurovault_daemon_running Daemon process running (1/0)",
            "# TYPE neurovault_daemon_running gauge",
            f"neurovault_daemon_running {1 if stats.get('daemon_running') else 0}",
            "",
        ]

        tiers = stats.get("tier_distribution", {})
        if isinstance(tiers, dict) and tiers:
            lines.extend(
                [
                    "# HELP neurovault_memories_by_tier Memories per tier",
                    "# TYPE neurovault_memories_by_tier gauge",
                ]
            )
            for tier, count in tiers.items():
                lines.append(f'neurovault_memories_by_tier{{tier="{self._escape_label(tier)}"}} {int(count)}')

        sources = stats.get("source_distribution", {})
        if isinstance(sources, dict) and sources:
            lines.extend(
                [
                    "",
                    "# HELP neurovault_memories_by_source Memories per source",
                    "# TYPE neurovault_memories_by_source gauge",
                ]
            )
            for source, count in sources.items():
                lines.append(
                    f'neurovault_memories_by_source{{source="{self._escape_label(source)}"}} {int(count)}'
                )

        pipeline = stats.get("pipeline", {})
        if isinstance(pipeline, dict):
            lines.extend(
                [
                    "",
                    "# HELP neurovault_pipeline_ingested_total Pipeline ingested count",
                    "# TYPE neurovault_pipeline_ingested_total counter",
                    f"neurovault_pipeline_ingested_total {int(pipeline.get('ingested', 0))}",
                    "",
                    "# HELP neurovault_pipeline_errors_total Pipeline error count",
                    "# TYPE neurovault_pipeline_errors_total counter",
                    f"neurovault_pipeline_errors_total {int(pipeline.get('errors', 0))}",
                ]
            )

        return "\n".join(lines) + "\n"

    @staticmethod
    def _escape_label(value: Any) -> str:
        text = str(value)
        return text.replace("\\", "\\\\").replace('"', '\\"')
