from __future__ import annotations

import logging
from contextlib import contextmanager
from typing import Generator

from hdbcli import dbapi  # SAP HANA Client — pip install hdbcli

from hanaflow.config import ConnectorConfig

logger = logging.getLogger(__name__)


class HANAConnector:
    """
    Thin wrapper around hdbcli.dbapi.Connection.

    Supports both context-manager usage (`with HANAConnector(...) as conn`)
    and explicit open/close.
    """

    def __init__(self, config: ConnectorConfig) -> None:
        config.validate()
        self._config = config
        self._connection: dbapi.Connection | None = None


    def connect(self) -> dbapi.Connection:
        cfg = self._config
        logger.info("Connecting to SAP HANA at %s:%d as %s …", cfg.host, cfg.port, cfg.user)

        self._connection = dbapi.connect(
            address=cfg.host,
            port=cfg.port,
            user=cfg.user,
            password=cfg.password,
            encrypt=cfg.encrypt,
            sslValidateCertificate=cfg.encrypt,
        )

        logger.info("Connected successfully.")
        return self._connection

    def disconnect(self) -> None:
        """Close the active connection if open."""
        if self._connection and self._connection.isconnected():
            self._connection.close()
            logger.info("HANA connection closed.")
        self._connection = None


    def __enter__(self) -> dbapi.Connection:
        return self.connect()

    def __exit__(self, exc_type, exc_val, exc_tb) -> None:
        self.disconnect()


    @property
    def connection(self) -> dbapi.Connection:
        if self._connection is None or not self._connection.isconnected():
            raise RuntimeError("No active HANA connection. Call connect() first.")
        return self._connection

    @contextmanager
    def cursor(self) -> Generator[dbapi.Cursor, None, None]:
        cur = self.connection.cursor()
        try:
            yield cur
        finally:
            cur.close()

    def test_connection(self) -> str:
        with self.cursor() as cur:
            cur.execute("SELECT VERSION FROM SYS.M_DATABASE")
            row = cur.fetchone()
            version = row[0] if row else "unknown"
        return version  # ← fixed