import logging
import os
import threading
from pathlib import Path

from dataiku.core.base import is_container_exec

from backends.explorer.factories.db_handler_factory import DbHandlerFactory
from graph.connections.db_handler import DbHandler
from graph.connections.kuzu import KuzuLocalDbHandler, KuzuLocalReplicaDbHandler

EXPLORER_DB_DOWNLOAD_LOCK = threading.Lock()

logger = logging.getLogger(__name__)


class KuzuDbHandlerFactory(DbHandlerFactory):
    """
    Factory class for creating database instance objects specifically for the explorer context.
    """

    def get_db_handler(self) -> DbHandler:
        relative_path_to_db = Path(f"built-graphs/{self.snapshot_id}")
        logger.info(f"Retrieve db from path : {relative_path_to_db}")

        db_folder_type = self.db_folder.get_info(sensitive_info=True)["type"]
        if db_folder_type == "Filesystem" and not is_container_exec():
            path_to_db = Path(os.path.join(self.db_folder.get_path(), relative_path_to_db, "db.kz"))
            return KuzuLocalDbHandler(db_path=path_to_db)
        else:
            path_to_db = Path(os.path.join(relative_path_to_db, "db.kz"))
            # Guard against the following situtation that happens only the first time the graph is visited:
            # 1. several concurrent requests to a graph without a replica downloaded yet
            # 2. the first request will trigger the download
            # 3. the subsequent ones used to use a malformed or non existing db, leading to empty results
            # To cover for this situation in a multi-threaded environment, we use a lock so the subsequent requests wait for the download to be complete.
            # This hack(-ish) fix will not work in a multi process environment though.
            # That's ok given the timeline we have to release the v1.0.0 of Visual Graph.
            with EXPLORER_DB_DOWNLOAD_LOCK:
                return KuzuLocalReplicaDbHandler(db_path=path_to_db, db_folder=self.db_folder)

