import importlib.util
from functools import lru_cache
from typing import Any


@lru_cache(maxsize=None)
def _has_module(module_name: str) -> bool:
    try:
        return importlib.util.find_spec(module_name) is not None
    except ModuleNotFoundError:
        return False


@lru_cache(maxsize=1)
def _get_clickhouse_engines():
    if not _has_module("clickhouse_sqlalchemy.engines"):
        return None

    try:
        from clickhouse_sqlalchemy import engines

        return engines
    except Exception:
        return None


@lru_cache(maxsize=1)
def _starrocks_ready() -> bool:
    if not _has_module("starrocks.dialect"):
        return False

    try:
        from tushare_models.core.dialect import TSStarRocksDDLCompiler  # noqa: F401

        return True
    except Exception:
        return False


@lru_cache(maxsize=1)
def _databend_ready() -> bool:
    if not _has_module("databend_sqlalchemy.databend_dialect"):
        return False

    try:
        from tushare_models.core.dialect import TSDatabendDDLCompiler  # noqa: F401

        return True
    except Exception:
        return False


def apply_table_dialect_options(model_cls: type[Any]) -> None:
    primary_key = getattr(model_cls, "__primary_key__", None)
    if not primary_key:
        return

    table = model_cls.__table__

    engines = _get_clickhouse_engines()
    if engines is not None:
        try:
            setattr(table, "engine", engines.ReplacingMergeTree(order_by=primary_key))
        except Exception:
            pass

    if _starrocks_ready():
        try:
            table.dialect_options["starrocks"].update(  # type: ignore
                {
                    "primary_key": ",".join(primary_key),
                    "order_by": ",".join(primary_key),
                }
            )
        except Exception:
            pass

    if _databend_ready():
        try:
            table.dialect_options["databend"].update(  # type: ignore
                {
                    "cluster_by": primary_key,
                }
            )
        except Exception:
            pass

    try:
        table.dialect_options["doris"].update(  # type: ignore
            {
                "unique_key": primary_key,
            }
        )
    except Exception:
        pass
