#include <exception>
#include <iostream>
#include <spdlog/spdlog.h>
#ifdef _WIN32
#include <io.h>
#include <fcntl.h>
#endif
#include "../provider/base/bootstrap.hpp"
#include "../service/base/bootstrap.hpp"
#include "../protocol/transform/facade.hpp"
#include "./server.hpp"

namespace lsp::core
{
    LspServer::LspServer(size_t concurrency) :
        async_executor_(4)
    {
        spdlog::info("Initializing LSP server with {} worker threads", concurrency);

        InitializeCoreServices();
        InitializeExtensionServices();

        spdlog::debug("LSP server initialized with {} providers.", dispatcher_.GetAllSupportedMethods().size());
    }

    LspServer::~LspServer()
    {
        is_shutting_down_ = true;
        spdlog::info("LSP server shutting down...");
    }

    void LspServer::Run()
    {
        spdlog::info("LSP server starting main loop...");

        // 设置二进制模式
#ifdef _WIN32
        _setmode(_fileno(stdout), _O_BINARY);
        _setmode(_fileno(stdin), _O_BINARY);
#endif

        while (!is_shutting_down_)
        {
            try
            {
                std::optional<std::string> message = ReadMessage();
                if (!message)
                {
                    if (std::cin.eof())
                    {
                        spdlog::info("End of input stream, exiting main loop");
                        break; // EOF
                    }
                    spdlog::debug("No message received, continuing...");
                    continue;
                }

                HandleMessage(*message);
            }
            catch (const std::exception& e)
            {
                spdlog::error("Error in main loop: {}", e.what());
            }
        }
        spdlog::info("LSP server main loop ended");
    }

    std::optional<std::string> LspServer::ReadMessage()
    {
        std::string line;
        size_t content_length = 0;

        // 读取 LSP Header
        while (std::getline(std::cin, line))
        {
            // 去掉尾部 \r
            if (!line.empty() && line.back() == '\r')
            {
                line.pop_back();
            }

            if (line.empty())
            {
                break; // 空行表示 header 结束
            }

            if (line.find("Content-Length:") == 0)
            {
                std::string length_str = line.substr(15); // 跳过 "Content-Length:"
                size_t start = length_str.find_first_not_of(" ");
                if (start != std::string::npos)
                {
                    length_str = length_str.substr(start);
                    try
                    {
                        content_length = std::stoul(length_str);
                        spdlog::trace("Content-Length: {}", content_length);
                    }
                    catch (const std::exception& e)
                    {
                        spdlog::error("Failed to parse Content-Length: {}", e.what());
                        return std::nullopt;
                    }
                }
            }
        }

        if (content_length == 0)
        {
            spdlog::debug("No Content-Length found in header");
            return std::nullopt;
        }

        // 读取内容体
        std::string body(content_length, '\0');
        std::cin.read(&body[0], content_length);

        if (std::cin.gcount() != static_cast<std::streamsize>(content_length))
        {
            spdlog::error("Read incomplete message body, expected: {}, got: {}", content_length, std::cin.gcount());
            return std::nullopt;
        }

        spdlog::trace("Received message: {}", body);
        return body;
    }

    void LspServer::HandleMessage(const std::string& raw_message)
    {
        if (auto notification = transform::Deserialize<protocol::NotificationMessage>(raw_message))
            HandleNotification(*notification);
        else if (auto request = transform::Deserialize<protocol::RequestMessage>(raw_message))
            HandleRequest(*request);
        else if (auto response = transform::Deserialize<protocol::ResponseMessage>(raw_message))
            HandleResponse(*response);
        else
            spdlog::error("Failed to deserialize message as any LSP message type");
    }

    void LspServer::HandleRequest(const protocol::RequestMessage& request)
    {
        std::string request_id = transform::debug::GetIdString(request.id);
        spdlog::debug("Processing request - id: {}, method: {}", request_id, request.method);

        // 检查是否可以处理请求
        if (!CanProcessRequest(request.method))
        {
            SendStateError(request);
        }
        else
        {
            // 决定同步还是异步处理
            if (RequiresSyncProcessing(request.method))
            {
                SendResponse(dispatcher_.Dispatch(request));
            }
            else
            {
                // 异步处理
                async_executor_.Submit(request_id, [this, request]() -> std::optional<std::string> {
                    if (is_shutting_down_)
                    {
                        spdlog::debug("Skipping request {} due to shutdown", request.method);
                        return std::nullopt;
                    }

                    try
                    {
                        return dispatcher_.Dispatch(request);
                    }
                    catch (const std::exception& e)
                    {
                        spdlog::error("Request processing failed: {}", e.what());
                        return provider::BuildErrorResponseMessage(request, protocol::ErrorCodes::InternalError, e.what());
                    } }, [this](const std::string& response) { SendResponse(response); });
            }
            spdlog::debug("Processing request method: {}", request.method);
        }
    }

    void LspServer::HandleNotification(const protocol::NotificationMessage& notification)
    {
        spdlog::debug("Processing notification - method: {}", notification.method);

        try
        {
            dispatcher_.Dispatch(notification);
        }
        catch (const std::exception& e)
        {
            spdlog::error("Notification processing failed for '{}': {}", notification.method, e.what());
        }
    }

    void LspServer::HandleResponse(const protocol::ResponseMessage& response)
    {
        std::string id_str = transform::debug::GetIdString(response.id);
        spdlog::debug("Received response - id: {}", id_str);
    }

    void LspServer::OnLifecycleEvent(provider::ServerLifecycleEvent event)
    {
        switch (event)
        {
        case provider::ServerLifecycleEvent::kInitializing:
            spdlog::info("Server initializing...");
            break;

        case provider::ServerLifecycleEvent::kInitialized:
            is_initialized_ = true;
            spdlog::info("Server initialized successfully");
            break;

        case provider::ServerLifecycleEvent::kInitializeFailed:
            is_initialized_ = false;
            spdlog::error("Server initialization failed");
            break;

        case provider::ServerLifecycleEvent::kShuttingDown:
            is_shutting_down_ = true;
            spdlog::info("Server entering shutdown state");
            break;

        case provider::ServerLifecycleEvent::kShutdown:
            is_shutting_down_ = true;
            spdlog::info("Server shutdown complete");
            break;
        }
    }

    bool LspServer::RequiresSyncProcessing(const std::string& method) const
    {
        static const std::unordered_set<std::string> sync_methods = {
            "initialize",
            "shutdown"
        };

        return sync_methods.count(method) > 0;
    }

    bool LspServer::CanProcessRequest(const std::string& method) const
    {
        if (!is_initialized_)
            return method == "initialize" || method == "exit";

        if (is_shutting_down_)
            return method == "exit";

        return true;
    }

    void LspServer::HandleCancelRequest(const protocol::NotificationMessage& notification)
    {
        spdlog::info("Handle cancel request - method: {}", notification.method);
    }

    void LspServer::SendResponse(const std::string& response)
    {
        std::lock_guard<std::mutex> lock(output_mutex_);

        size_t byte_length = response.length();
        std::string header = "Content-Length: " + std::to_string(byte_length) + "\r\n\r\n";

        // 发送 header 和 body
        std::cout.write(header.c_str(), header.length());
        std::cout.write(response.c_str(), response.length());
        std::cout.flush();

        spdlog::trace("Response sent - length: {}", byte_length);
        spdlog::trace("Response sent - body: {}", response);
    }

    void LspServer::InitializeCoreServices()
    {
        spdlog::debug("Initializing core services...");

        dispatcher_.SetRequestScheduler(&async_executor_);

        dispatcher_.RegisterLifecycleCallback(
            [this](provider::ServerLifecycleEvent event) {
                OnLifecycleEvent(event);
            });
        provider::RegisterAllProviders(dispatcher_);

        spdlog::debug("Core services initialized");
    }

    void LspServer::InitializeExtensionServices()
    {
        spdlog::debug("Initializing extension services...");

        service::RegisterAllServices(service_registry_, async_executor_);
        dispatcher_.SetSeviceRegistry(&service_registry_);

        spdlog::debug("Extension services initialized");
    }

    void LspServer::SendError(const protocol::RequestMessage& request, protocol::ErrorCodes code, const std::string& message)
    {
        spdlog::warn("Sending error response - method: {}, code: {}, message: {}", request.method, static_cast<int>(code), message);
        std::string error_response = provider::BuildErrorResponseMessage(request, code, message);
        SendResponse(error_response);
    }

    void LspServer::SendStateError(const protocol::RequestMessage& request)
    {
        if (!is_initialized_)
            SendError(request, protocol::ErrorCodes::ServerNotInitialized, "Server not initialized");
        else if (is_shutting_down_)
            SendError(request, protocol::ErrorCodes::InvalidRequest, "Server is shutting down, only 'exit' is allowed");
        else
            SendError(request, protocol::ErrorCodes::InternalError, "Request not allowed in current state");
    }
}
