"""Client ClickHouse singleton partagé pour la suite de sécurité JA4."""
import clickhouse_connect
from typing import Optional

from .settings import settings


class ClickHouseClient:
    """Client ClickHouse singleton avec reconnexion automatique.

    Attributs :
        _client : instance du client clickhouse_connect sous-jacent,
                  ou None si la connexion n'est pas encore établie.
    """

    def __init__(self):
        """Initialise le client sans ouvrir de connexion immédiate."""
        self._client: Optional[clickhouse_connect.driver.client.Client] = None

    def connect(self) -> clickhouse_connect.driver.client.Client:
        """Retourne un client connecté, en créant ou rétablissant la connexion si nécessaire."""
        if self._client is None or not self._ping():
            self._client = clickhouse_connect.get_client(
                host=settings.CLICKHOUSE_HOST,
                port=settings.CLICKHOUSE_PORT,
                database=settings.CLICKHOUSE_DB,
                user=settings.CLICKHOUSE_USER,
                password=settings.CLICKHOUSE_PASSWORD,
                connect_timeout=10,
            )
        return self._client

    def _ping(self) -> bool:
        """Vérifie que la connexion existante est active. Retourne False en cas d'erreur."""
        try:
            if self._client:
                self._client.ping()
                return True
        except Exception:
            pass
        return False

    def query(self, query: str, params: Optional[dict] = None):
        """Exécute une requête SELECT et retourne le résultat."""
        return self.connect().query(query, params)

    def command(self, query: str, params: Optional[dict] = None):
        """Exécute une commande DDL/DML (INSERT, CREATE, TRUNCATE, etc.)."""
        return self.connect().command(query, parameters=params)

    def insert(self, table: str, data, column_names=None):
        """Insère des données dans la table cible."""
        return self.connect().insert(table, data, column_names=column_names)

    def close(self):
        """Ferme la connexion et réinitialise le client interne."""
        if self._client:
            self._client.close()
            self._client = None


_client: Optional[ClickHouseClient] = None


def get_client() -> ClickHouseClient:
    """Retourne l'instance singleton du ClickHouseClient, en la créant si nécessaire."""
    global _client
    if _client is None:
        _client = ClickHouseClient()
    return _client
