"""Built-in health check implementations."""
import inspect
from typing import Any, Callable

from fk_utils.health.base import HealthCheck

_HEALTHY = "healthy"


class MongoDBCheck(HealthCheck):
    """Validates MongoDB connectivity via ping."""

    def __init__(self, client: Any) -> None:
        self._client = client

    @property
    def name(self) -> str:
        return "mongodb"

    def check(self) -> str:
        try:
            self._client.admin.command("ping")
            return _HEALTHY
        except Exception as e:
            return f"unhealthy: {e}"


class PostgreSQLCheck(HealthCheck):
    """
    Validates PostgreSQL connectivity via SELECT 1.

    Accepts a ``session_factory``: a callable that returns either a SQLAlchemy
    Session directly or a generator yielding one (FastAPI's ``Depends`` pattern).
    Generator factories are properly closed after the check to avoid leaking
    connections.

    Examples::

        # FastAPI — same factory you use in Depends
        PostgreSQLCheck(session_factory=get_db)

        # Flask / standalone
        PostgreSQLCheck(session_factory=lambda: db.session)
    """

    def __init__(self, session_factory: Callable) -> None:
        self._factory = session_factory

    @property
    def name(self) -> str:
        return "postgresql"

    def check(self) -> str:
        gen = None
        try:
            result = self._factory()
            if inspect.isgenerator(result):
                gen = result
                session = next(gen)
            else:
                session = result
            try:
                from sqlalchemy import text
                session.execute(text("SELECT 1"))
            except ImportError:
                session.execute("SELECT 1")
            return _HEALTHY
        except Exception as e:
            return f"unhealthy: {e}"
        finally:
            if gen is not None:
                gen.close()


class DjangoPostgreSQLCheck(HealthCheck):
    """
    Validates PostgreSQL connectivity for Django services.

    Uses Django's managed ``connection`` directly — no session factory needed.

    Example::

        from fk_utils.health.checks import DjangoPostgreSQLCheck

        DjangoPostgreSQLCheck()
    """

    @property
    def name(self) -> str:
        return "postgresql"

    def check(self) -> str:
        try:
            from django.db import connection
            with connection.cursor() as cursor:
                cursor.execute("SELECT 1")
            return _HEALTHY
        except Exception as e:
            return f"unhealthy: {e}"
