#include <iostream>
#include <spdlog/sinks/stdout_sinks.h>
#include <spdlog/sinks/basic_file_sink.h>
#include "./args_parser.hpp"

namespace lsp::utils
{
    ArgsParser& ArgsParser::Instance()
    {
        static ArgsParser instance;
        return instance;
    }

    const ServerConfig& ArgsParser::Parse(int argc, char* argv[])
    {
        config_ = ServerConfig {};
        bool use_stdio = false;
        for (int i = 1; i < argc; ++i)
        {
            std::string arg = argv[i];

            if (arg == "--help")
            {
                config_.show_help = true;
                return config_;
            }

            if (arg == "--log=trace")
                config_.log_level = spdlog::level::trace;
            else if (arg == "--log=debug")
                config_.log_level = spdlog::level::debug;
            else if (arg == "--log=info")
                config_.log_level = spdlog::level::info;
            else if (arg == "--log=warn")
                config_.log_level = spdlog::level::warn;
            else if (arg == "--log=error")
                config_.log_level = spdlog::level::err;
            else if (arg == "--log=off")
                config_.log_level = spdlog::level::off;
            else if (arg.find("--log-file=") == 0)
                config_.log_file = arg.substr(11);
            else if (arg == "--log-stderr")
                config_.use_stderr = true;
            else if (arg.find("--interpreter=") == 0)
                config_.interpreter_path = arg.substr(14);
            else if (arg.find("--threads=") == 0)
            {
                std::string count_str = arg.substr(10);
                try
                {
                    size_t count = std::stoul(count_str);
                    if (count == 0 || count > 32)
                    {
                        std::cerr << "[TSL-LSP] Error: Thread count must be between 1 and 32" << std::endl;
                        std::exit(1);
                    }
                    config_.thread_count = count;
                }
                catch (const std::exception&)
                {
                    std::cerr << "[TSL-LSP] Error: Invalid thread count: " << count_str << std::endl;
                    std::exit(1);
                }
            }
            else if (arg == "--stdio")
            {
                use_stdio = true;
            }
            else
            {
                std::cerr << "[TSL-LSP] Error: Unknown argument: " << arg << std::endl;
                std::cerr << "Use --help for usage information" << std::endl;
            }
        }
        std::cerr << "TSL Language Server " << __DATE__ << std::endl;
        if (use_stdio)
            std::cerr << "[TSL-LSP] JosnRPc using stdio" << std::endl;

        // config_.interpreter_path = "/mnt/c/Programs/Tinysoft/TSLGen2/";
        return config_;
    }

    const ServerConfig& ArgsParser::GetConfig() const
    {
        return config_;
    }

    void ArgsParser::SetupLogger(const ServerConfig& config)
    {
        std::vector<spdlog::sink_ptr> sinks;

        if (config.use_stderr)
            sinks.push_back(std::make_shared<spdlog::sinks::stderr_sink_mt>());

        if (!config.log_file.empty())
        {
            try
            {
                sinks.push_back(std::make_shared<spdlog::sinks::basic_file_sink_mt>(config.log_file, true));
            }
            catch (const std::exception& e)
            {
                std::cerr << "[TSL-LSP] Failed to create log file: " << e.what() << std::endl;
            }
        }

        auto logger = std::make_shared<spdlog::logger>("tsl_lsp", sinks.begin(), sinks.end());
        logger->set_level(config.log_level);
        logger->set_pattern("[%Y-%m-%d %H:%M:%S] [%^%l%$] %v");

        spdlog::set_default_logger(logger);
        spdlog::flush_on(spdlog::level::warn);
    }

    void ArgsParser::PrintHelp(const std::string& program_name)
    {
        // 获取硬件线程数
        size_t hardware_threads = std::thread::hardware_concurrency();
        if (hardware_threads == 0)
            hardware_threads = 0; // 表示无法检测

        std::cout << "TSL Language Server Protocol (LSP) Server\n"
                  << "Version: " << __DATE__ << " build\n"
                  << "\n"
                  << "Usage: " << program_name << " [options]\n"
                  << "\n"
                  << "Options:\n"
                  << "  --help              Show this help message and exit\n"
                  << "\n"
                  << "Interpreter options:\n"
                  << "  --interpreter=PATH  Set path to TSL interpreter executable\n"
                  << "                      Required for some language features\n"
                  << "\n"
                  << "Logging options:\n"
                  << "  --log=LEVEL         Set log level (trace, debug, info, warn, error, off)\n"
                  << "                      Default: info\n"
                  << "  --log-file=PATH     Write logs to file at PATH\n"
                  << "  --log-stderr        Output logs to stderr\n"
                  << "\n"
                  << "Performance options:\n"
                  << "  --threads=N         Set number of worker threads (1-32)\n"
                  << "                      Default: 4\n";

        // 显示硬件信息
        if (hardware_threads > 0)
            std::cout << "                      Hardware threads available: " << hardware_threads << "\n";
        else
            std::cout << "                      Hardware threads: unable to detect\n";

        std::cout << "\n"
                  << "Examples:\n"
                  << "  # Run with debug logging to stderr\n"
                  << "  " << program_name << " --log=debug --log-stderr\n"
                  << "\n"
                  << "  # Run with 8 worker threads and log to file\n"
                  << "  " << program_name << " --threads=8 --log-file=server.log\n"
                  << "\n"
                  << "  # Run with maximum hardware threads\n";

        if (hardware_threads > 0)
            std::cout << "  " << program_name << " --threads=" << hardware_threads << "\n";
        else
            std::cout << "  " << program_name << " --threads=16  # adjust based on your CPU\n";
    }

}
