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

namespace lsp::core
{
    void RequestDispatcher::SetRequestScheduler(scheduler::RequestScheduler* scheduler)
    {
        scheduler_ = scheduler;
        spdlog::debug("RequestScheduler set in dispatcher");
    }

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

        providers_[method] = provider;
        spdlog::info("Registered request provider '{}' for method: {}", provider->GetProviderName(), method);
    }

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

        notification_providers_[method] = provider;
        spdlog::info("Registered notification provider '{}' for method: {}", provider->GetProviderName(), method);
    }

    void RequestDispatcher::RegisterLifecycleCallback(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)
    {
        providers::ProviderContext context(
            scheduler_,
            [this](ServerLifecycleEvent event)
            {
                NotifyAllLifecycleListeners(event);
            });

        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 BuildErrorResponseMessage(request, protocol::ErrorCode::kInternalError, e.what());
            }
        }
        return HandleUnknownRequest(request);
    }

    void RequestDispatcher::Dispatch(const protocol::NotificationMessage& notification)
    {
        // 创建 provider context
        providers::ProviderContext context(
            scheduler_,
            [this](ServerLifecycleEvent event)
            {
                NotifyAllLifecycleListeners(event);
            });

        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;
    }

    std::string RequestDispatcher::BuildErrorResponseMessage(const protocol::RequestMessage& request, protocol::ErrorCode code, const std::string& message)
    {
        return providers::IRequestProvider::BuildErrorResponseMessage(request, code, message);
    }

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

        std::string event_name;
        switch (event)
        {
        case ServerLifecycleEvent::kInitializing:
            event_name = "Initializing";
            break;
        case ServerLifecycleEvent::kInitialized:
            event_name = "Initialized";
            break;
        case ServerLifecycleEvent::kInitializeFailed:
            event_name = "InitializeFailed";
            break;
        case ServerLifecycleEvent::kShuttingDown:
            event_name = "ShuttingDown";
            break;
        case 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 BuildErrorResponseMessage(request, protocol::ErrorCode::kMethodNotFound, "Method not found: " + request.method);
    }

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

}
