"""Data curator for ModernBERT training pipeline.

Since the telemetry system stores only SHA-256 query hashes (never actual text),
this module analyses routing_events to understand usage distribution and returns
stats for calibrating synthetic data generation.

``curate_from_telemetry`` will always return an empty ``examples`` list because
actual text cannot be recovered from hashes — but it populates ``stats`` so that
``SyntheticDataGenerator`` can mirror real-world model/tier distribution.
"""

from __future__ import annotations

import dataclasses
import logging
import sqlite3
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from pathlib import Path

logger = logging.getLogger(__name__)

# ---------------------------------------------------------------------------
# Canonical label constants (single source of truth for all training modules)
# ---------------------------------------------------------------------------

COMPLEXITY_LABELS: list[str] = ["trivial", "simple", "moderate", "complex", "expert"]
DOMAIN_LABELS: list[str] = ["coding", "writing", "analysis", "creative", "chat", "math", "data"]
QUALITY_LABELS: list[str] = ["low", "medium", "high", "maximum"]
PRIVACY_LABELS: list[str] = ["personal", "private", "external"]


@dataclasses.dataclass
class TrainingExample:
    """A single labelled training example for the ModernBERT classifier."""

    text: str
    """The query text used for classification (synthetic, never from telemetry)."""

    complexity_label: str
    """One of: trivial / simple / moderate / complex / expert."""

    domain_label: str
    """One of: coding / writing / analysis / creative / chat / math / data."""

    quality_label: str
    """One of: low / medium / high / maximum."""

    privacy_label: str
    """One of: personal / private / external."""


@dataclasses.dataclass
class TelemetryStats:
    """Distribution statistics derived from telemetry (no text, hashes only)."""

    total_events: int
    """Total routing events recorded."""

    model_counts: dict[str, int]
    """Count of routing decisions per model name."""

    tier_counts: dict[str, int]
    """Count of routing decisions per tier (rule_based / knn / modernbert / local)."""

    privacy_counts: dict[str, int]
    """Count of routing decisions per privacy level."""

    db_path: Path
    """Path to the telemetry database that was analysed."""


class DataCurator:
    """Curates training data from the telemetry SQLite database.

    Because actual query text is never stored (only SHA-256 hashes), this
    class cannot produce real training examples from telemetry.  Instead it
    analyses the routing distribution to provide calibration stats for the
    ``SyntheticDataGenerator``.

    Usage::

        curator = DataCurator()
        examples, stats = curator.curate_from_telemetry(db_path)
        # examples is always []
        # stats.model_counts tells you which models were used most
    """

    def curate_from_telemetry(
        self,
        db_path: Path,
        min_samples: int = 100,
    ) -> tuple[list[TrainingExample], TelemetryStats | None]:
        """Analyse the telemetry DB and return calibration stats.

        Returns an empty ``examples`` list because actual query text is not
        stored in telemetry (only SHA-256 hashes). The ``TelemetryStats``
        object contains routing distribution information useful for calibrating
        synthetic data generation.

        Args:
            db_path: Path to the telemetry SQLite database.
            min_samples: Minimum number of routing events required to produce
                meaningful stats.  If fewer events exist, ``stats`` is None.

        Returns:
            A tuple of ``([], stats)`` where ``stats`` is None when the DB is
            missing or has fewer than ``min_samples`` events.
        """
        if not db_path.exists():
            logger.debug("Telemetry DB not found at %s; returning empty stats.", db_path)
            return [], None

        try:
            with sqlite3.connect(db_path) as conn:
                # Total event count
                row = conn.execute("SELECT COUNT(*) FROM routing_events").fetchone()
                total = row[0] if row else 0

                if total < min_samples:
                    logger.debug(
                        "Telemetry DB has %d events (< min_samples=%d); stats not meaningful.",
                        total,
                        min_samples,
                    )
                    return [], None

                # Model distribution
                model_rows = conn.execute(
                    "SELECT model, COUNT(*) AS cnt FROM routing_events GROUP BY model ORDER BY cnt DESC"
                ).fetchall()
                model_counts: dict[str, int] = {r[0]: r[1] for r in model_rows}

                # Tier distribution
                tier_rows = conn.execute(
                    "SELECT tier_used, COUNT(*) AS cnt FROM routing_events GROUP BY tier_used ORDER BY cnt DESC"
                ).fetchall()
                tier_counts: dict[str, int] = {r[0]: r[1] for r in tier_rows}

                # Privacy level distribution
                privacy_rows = conn.execute(
                    "SELECT privacy_level, COUNT(*) AS cnt FROM routing_events GROUP BY privacy_level ORDER BY cnt DESC"
                ).fetchall()
                privacy_counts: dict[str, int] = {r[0]: r[1] for r in privacy_rows}

        except sqlite3.Error as exc:
            logger.warning("Failed to read telemetry DB at %s: %s", db_path, exc)
            return [], None

        stats = TelemetryStats(
            total_events=total,
            model_counts=model_counts,
            tier_counts=tier_counts,
            privacy_counts=privacy_counts,
            db_path=db_path,
        )

        # Privacy constraint: examples list is always empty.
        # Actual query text is irretrievable from SHA-256 hashes.
        return [], stats
