from collections.abc import Coroutine
import asyncio, threading
from typing import Any, Awaitable

import concurrent.futures


def wrap_concurrent_future(conc_fut: concurrent.futures.Future) -> asyncio.Future:
    current_loop = asyncio.get_running_loop()
    async_fut = current_loop.create_future()

    def transfer_result(cf):
        try:
            async_fut.set_result(cf.result())
        except Exception as e:
            async_fut.set_exception(e)

    conc_fut.add_done_callback(
        lambda f: current_loop.call_soon_threadsafe(transfer_result, f)
    )
    return async_fut


async def await_in_loop(target_loop: asyncio.AbstractEventLoop, coro: Coroutine) -> Any:
    conc_fut = asyncio.run_coroutine_threadsafe(coro, target_loop)
    current_loop = asyncio.get_running_loop()
    async_fut = current_loop.create_future()

    def transfer_result(cf):
        try:
            async_fut.set_result(cf.result())
        except Exception as e:
            async_fut.set_exception(e)

    if conc_fut.done():
        transfer_result(conc_fut)
    else:
        conc_fut.add_done_callback(
            lambda f: current_loop.call_soon_threadsafe(transfer_result, f)
        )

    return await async_fut


# def bridge_coro_to_userloop(coro: Awaitable, runtime_loop: asyncio.AbstractEventLoop) -> asyncio.Future:
#     """
#     在 user loop 中创建一个 future，然后用 runtime_loop 执行 coro，
#     执行完后将结果设置到 user loop 的 future 上。
#     无线程、全 async 实现。
#     """
#     user_loop = asyncio.get_running_loop()
#     user_future = user_loop.create_future()

#     async def transfer():
#         try:
#             result = await coro
#             user_loop.call_soon_threadsafe(user_future.set_result, result)
#         except Exception as e:
#             user_loop.call_soon_threadsafe(user_future.set_exception, e)

#     asyncio.run_coroutine_threadsafe(transfer(), runtime_loop)
#     return user_future

    
    
    
# import asyncio
# from typing import Callable, Awaitable
# import functools

# class LoopBridge:
#     @staticmethod
#     def submit(target_loop: AsyncLoopProxy, coro_func: Callable, *args, **kwargs) -> asyncio.Future:
#         """
#         将 coroutine 托管给指定 AsyncLoopProxy 执行，
#         并返回绑定到当前用户 loop 的 asyncio.Future
#         """
#         # 创建 coroutine object getter
#         if not asyncio.iscoroutinefunction(coro_func):
#             raise TypeError("Only coroutine functions can be scheduled")
        
#         coro_getter = functools.partial(coro_func, *args, **kwargs)
#         runtime_future = target_loop.submit(coro_getter)

#         # 当前用户 loop 上创建用户可 await 的 future
#         user_loop = asyncio.get_running_loop()
#         user_future = user_loop.create_future()

#         def transfer_result():
#             try:
#                 result = runtime_future.result()
#                 user_loop.call_soon_threadsafe(user_future.set_result, result)
#             except Exception as e:
#                 user_loop.call_soon_threadsafe(user_future.set_exception, e)

#         # 启动桥接
#         threading.Thread(target=transfer_result, daemon=True).start()
#         return user_future
