/* Copyright (c) 2025 Huawei Technologies Co., Ltd.
 * openUBMC is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
#ifndef OTEL_CUSTOM_LOG_HANDLER_H
#define OTEL_CUSTOM_LOG_HANDLER_H

#include <iostream>
#include <iomanip>
#include <chrono>
#include <ctime>
#include <string_view>
#include <syslog.h>
#include "opentelemetry/sdk/common/global_log_handler.h"
#include "logging.h"

namespace Otel {
namespace internal_log = opentelemetry::sdk::common::internal_log;

namespace Common {

static inline std::string_view get_file_name(std::string_view file)
{
    // 查找最后一个分隔符
    auto pos = file.find_last_of('/');
    return (pos != std::string_view::npos) ? file.substr(pos + 1) : file;
}

static inline std::string_view CustomLevelToString(internal_log::LogLevel level)
{
    switch (level)
    {
        case internal_log::LogLevel::Error:
            return "ERROR";
        case internal_log::LogLevel::Warning:
            return "WARNING";
        case internal_log::LogLevel::Info:
            return "INFO";
        case internal_log::LogLevel::Debug:
            return "DEBUG";
    }
    return "";
}

class CustomLogHandler : public internal_log::LogHandler
{
public:
    void Handle(internal_log::LogLevel level, const char *file, int line, const char *msg,
                const opentelemetry::sdk::common::AttributeMap &/* attributes */) noexcept
    {
        if (msg == nullptr || file == nullptr) {
            return;
        }
        std::stringstream output_s;
        // 获取当前时间点（含微秒）
        auto now = std::chrono::system_clock::now();
        // 转换为time_t（秒级精度）
        auto now_c = std::chrono::system_clock::to_time_t(now);
        // 转换为本地时间
        std::tm* local_time = std::localtime(&now_c);
        // 获取微秒部分
        auto us = std::chrono::duration_cast<std::chrono::microseconds>(now.time_since_epoch()) % 1000000;
        // 输出格式化时间（含微秒）
        output_s << std::put_time(local_time, "%Y-%m-%d %H:%M:%S");
        output_s << "." << std::setfill('0') << std::setw(6) << us.count();
        output_s << " " << m_module_name << " " << CustomLevelToString(level) << ": " << get_file_name(file);
        output_s << "(" << line << "): " << msg << std::endl;
        syslog(LOG_LOCAL5 | LOG_NOTICE, "%s", output_s.str().c_str());
    }

    void SetModuleName(const std::string_view &module_name)
    {
        m_module_name = module_name;
    }

private:
    std::string m_module_name = "unknown_service";
};

} // namespace Common
} // namespace Otel

#endif // OTEL_CUSTOM_LOG_HANDLER_H