#include <spdlog/spdlog.h>
#include <mutex>
#include "./dispacther.hpp"
#include "../protocol/transform/facade.hpp"

namespace lsp::core
{
    RequestDispatcher::RequestDispatcher()
    {
        // 预创建 lifecycle callback，避免每次调用时都创建新的 lambda
        context_lifecycle_callback_ = [this](provider::ServerLifecycleEvent event) {
            NotifyAllLifecycleListeners(event);
        };
    }

    void RequestDispatcher::SetRequestScheduler(scheduler::AsyncExecutor* scheduler)
    {
        async_executor_ = scheduler;
        spdlog::debug("RequestScheduler set in dispatcher");
    }

    void RequestDispatcher::SetSeviceRegistry(service::Registry* service_registry)
    {
        service_registry_ = service_registry;
        spdlog::debug("ServiceRegistry is set in dispatcher");
    }

    void RequestDispatcher::RegisterRequestProvider(std::shared_ptr<provider::IRequestProvider> provider)
    {
        std::unique_lock<std::shared_mutex> lock(providers_mutex_);
        std::string method = provider->GetMethod();

        providers_[method] = provider;
    }

    void RequestDispatcher::RegisterNotificationProvider(std::shared_ptr<provider::INotificationProvider> provider)
    {
        std::unique_lock<std::shared_mutex> lock(notification_providers_mutex_);
        std::string method = provider->GetMethod();

        notification_providers_[method] = provider;
    }

    void RequestDispatcher::RegisterLifecycleCallback(provider::LifecycleCallback callback)
    {
        std::lock_guard<std::mutex> lock(callbacks_mutex_);
        lifecycle_callbacks_.push_back(std::move(callback));
        spdlog::debug("Registered lifecycle callback");
    }

    std::string RequestDispatcher::Dispatch(const protocol::RequestMessage& request)
    {
        provider::ExecutionContext context(context_lifecycle_callback_, *async_executor_, *service_registry_);

        std::shared_lock<std::shared_mutex> lock(providers_mutex_);
        auto it = providers_.find(request.method);
        if (it != providers_.end())
        {
            auto provider = it->second;
            lock.unlock();
            try
            {
                spdlog::debug("Dispatching request [{}] to provider [{}]", request.method, provider->GetProviderName());
                return provider->ProvideResponse(request, context);
            }
            catch (const std::exception& e)
            {
                spdlog::error("Provider error for method [{}]: {}", request.method, e.what());
                return provider::BuildErrorResponseMessage(request, protocol::ErrorCodes::InternalError, e.what());
            }
        }
        return HandleUnknownRequest(request);
    }

    void RequestDispatcher::Dispatch(const protocol::NotificationMessage& notification)
    {
        provider::ExecutionContext context(context_lifecycle_callback_, *async_executor_, *service_registry_);

        std::shared_lock<std::shared_mutex> lock(notification_providers_mutex_);
        auto it = notification_providers_.find(notification.method);
        if (it != notification_providers_.end())
        {
            auto provider = it->second;
            lock.unlock();

            try
            {
                spdlog::debug("Dispatching notification [{}] to provider [{}]", notification.method, provider->GetProviderName());
                provider->HandleNotification(notification, context);
                return;
            }
            catch (const std::exception& e)
            {
                spdlog::error("Notification provider [{}] threw exception for method '{}': {}", provider->GetProviderName(), notification.method, e.what());
                return;
            }
        }
        HandleUnknownNotification(notification);
    }

    bool RequestDispatcher::SupportsRequest(const std::string& method) const
    {
        std::shared_lock<std::shared_mutex> lock(providers_mutex_);
        return providers_.find(method) != providers_.end();
    }

    std::vector<std::string> RequestDispatcher::GetSupportedRequests() const
    {
        std::shared_lock<std::shared_mutex> lock(providers_mutex_);
        std::vector<std::string> methods;
        methods.reserve(providers_.size());
        for (const auto& [method, _] : providers_)
            methods.push_back(method);
        return methods;
    }

    std::vector<std::string> RequestDispatcher::GetSupportedNotifications() const
    {
        std::shared_lock<std::shared_mutex> lock(notification_providers_mutex_);
        std::vector<std::string> methods;
        methods.reserve(notification_providers_.size());
        for (const auto& [method, provider] : notification_providers_)
            methods.push_back(method);
        return methods;
    }

    std::vector<std::string> RequestDispatcher::GetAllSupportedMethods() const
    {
        auto requests = GetSupportedRequests();
        auto notifications = GetSupportedNotifications();

        // 合并两个列表
        requests.insert(requests.end(), notifications.begin(), notifications.end());
        return requests;
    }

    void RequestDispatcher::NotifyAllLifecycleListeners(provider::ServerLifecycleEvent event)
    {
        std::lock_guard<std::mutex> lock(callbacks_mutex_);

        std::string event_name;
        switch (event)
        {
        case provider::ServerLifecycleEvent::kInitializing:
            event_name = "Initializing";
            break;
        case provider::ServerLifecycleEvent::kInitialized:
            event_name = "Initialized";
            break;
        case provider::ServerLifecycleEvent::kInitializeFailed:
            event_name = "InitializeFailed";
            break;
        case provider::ServerLifecycleEvent::kShuttingDown:
            event_name = "ShuttingDown";
            break;
        case provider::ServerLifecycleEvent::kShutdown:
            event_name = "Shutdown";
            break;
        }

        spdlog::info("Lifecycle event: {}", event_name);

        for (const auto& callback : lifecycle_callbacks_)
        {
            try
            {
                callback(event);
            }
            catch (const std::exception& e)
            {
                spdlog::error("Lifecycle callback error: {}", e.what());
            }
        }
    }

    std::string RequestDispatcher::HandleUnknownRequest(const protocol::RequestMessage& request)
    {
        return provider::BuildErrorResponseMessage(request, protocol::ErrorCodes::MethodNotFound, "Method not found: " + request.method);
    }

    void RequestDispatcher::HandleUnknownNotification(const protocol::NotificationMessage& notification)
    {
        spdlog::debug("No handler found for notification: {}", notification.method);
        // 通知没有响应，所以只记录日志
    }

}
