#pragma once

#include <extra2d/core/service_interface.h>
#include <extra2d/core/service_locator.h>
#include <extra2d/core/types.h>
#include <cstdarg>
#include <string>
#include <type_traits>

namespace extra2d {

/**
 * @brief 日志级别枚举
 */
enum class LogLevel {
    Trace = 0,
    Debug = 1,
    Info = 2,
    Warn = 3,
    Error = 4,
    Fatal = 5,
    Off = 6
};

/**
 * @brief 日志服务接口
 */
class ILogger : public IService {
public:
    virtual ~ILogger() = default;
    
    /**
     * @brief 设置日志级别
     */
    virtual void setLevel(LogLevel level) = 0;
    
    /**
     * @brief 获取日志级别
     */
    virtual LogLevel getLevel() const = 0;
    
    /**
     * @brief 检查日志级别是否启用
     */
    virtual bool isEnabled(LogLevel level) const = 0;
    
    /**
     * @brief 记录日志（格式化）
     */
    virtual void log(LogLevel level, const char* fmt, ...) = 0;
    
    /**
     * @brief 记录日志（字符串）
     */
    virtual void log(LogLevel level, const std::string& msg) = 0;
    
    /**
     * @brief Trace级别日志
     */
    virtual void trace(const char* fmt, ...) = 0;
    
    /**
     * @brief Debug级别日志
     */
    virtual void debug(const char* fmt, ...) = 0;
    
    /**
     * @brief Info级别日志
     */
    virtual void info(const char* fmt, ...) = 0;
    
    /**
     * @brief Warn级别日志
     */
    virtual void warn(const char* fmt, ...) = 0;
    
    /**
     * @brief Error级别日志
     */
    virtual void error(const char* fmt, ...) = 0;
    
    /**
     * @brief Fatal级别日志
     */
    virtual void fatal(const char* fmt, ...) = 0;
    
    ServiceInfo getServiceInfo() const override {
        ServiceInfo info;
        info.name = "Logger";
        info.priority = ServicePriority::Core;
        info.enabled = true;
        return info;
    }
};

/**
 * @brief 控制台日志服务实现
 */
class ConsoleLogger : public ILogger {
public:
    ConsoleLogger();
    ~ConsoleLogger() override;
    
    bool initialize() override;
    void shutdown() override;
    
    void setLevel(LogLevel level) override;
    LogLevel getLevel() const override;
    bool isEnabled(LogLevel level) const override;
    
    void log(LogLevel level, const char* fmt, ...) override;
    void log(LogLevel level, const std::string& msg) override;
    
    void trace(const char* fmt, ...) override;
    void debug(const char* fmt, ...) override;
    void info(const char* fmt, ...) override;
    void warn(const char* fmt, ...) override;
    void error(const char* fmt, ...) override;
    void fatal(const char* fmt, ...) override;

private:
    void output(LogLevel level, const char* msg);
    const char* getLevelString(LogLevel level);

    LogLevel level_;
    class Impl;
    UniquePtr<Impl> impl_;

    // 服务注册元数据
    E2D_AUTO_REGISTER_SERVICE(ILogger, ConsoleLogger);
};

} // namespace extra2d

// 格式化辅助函数 - 将参数转换为字符串
namespace extra2d {
namespace detail {
    template<typename T>
    std::string to_string(T&& value) {
        using Decayed = std::decay_t<T>;
        if constexpr (std::is_same_v<Decayed, std::string>) {
            return value;
        } else if constexpr (std::is_same_v<Decayed, const char*>) {
            return value ? value : "(null)";
        } else if constexpr (std::is_arithmetic_v<Decayed>) {
            if constexpr (std::is_same_v<Decayed, bool>) {
                return value ? "true" : "false";
            } else if constexpr (std::is_floating_point_v<Decayed>) {
                return std::to_string(value);
            } else {
                return std::to_string(value);
            }
        } else {
            return "<?>";
        }
    }
    
    inline void format_impl(std::string& result, const char* fmt) {
        result += fmt;
    }
    
    template<typename T, typename... Args>
    void format_impl(std::string& result, const char* fmt, T&& value, Args&&... args) {
        const char* p = fmt;
        while (*p) {
            if (*p == '{' && *(p + 1) == '}') {
                result += to_string(std::forward<T>(value));
                format_impl(result, p + 2, std::forward<Args>(args)...);
                return;
            }
            result += *p++;
        }
        // 没有更多的 {}，追加剩余参数（不应该发生）
        result += " ";
        result += to_string(std::forward<T>(value));
        format_impl(result, p, std::forward<Args>(args)...);
    }
}

template<typename... Args>
std::string format_str(const char* fmt, Args&&... args) {
    if constexpr (sizeof...(args) == 0) {
        return std::string(fmt);
    } else {
        std::string result;
        detail::format_impl(result, fmt, std::forward<Args>(args)...);
        return result;
    }
}
}

// 便捷宏 - 自动获取日志服务
#define E2D_LOG(level, ...) \
    do { \
        if (auto logService = ::extra2d::ServiceLocator::instance().tryGetService<::extra2d::ILogger>()) { \
            if (logService->isEnabled(level)) { \
                logService->log(level, ::extra2d::format_str(__VA_ARGS__)); \
            } \
        } \
    } while(0)

#define E2D_LOG_TRACE(...) \
    E2D_LOG(::extra2d::LogLevel::Trace, __VA_ARGS__)

#define E2D_LOG_DEBUG(...) \
    E2D_LOG(::extra2d::LogLevel::Debug, __VA_ARGS__)

#define E2D_LOG_INFO(...) \
    E2D_LOG(::extra2d::LogLevel::Info, __VA_ARGS__)

#define E2D_LOG_WARN(...) \
    E2D_LOG(::extra2d::LogLevel::Warn, __VA_ARGS__)

#define E2D_LOG_ERROR(...) \
    E2D_LOG(::extra2d::LogLevel::Error, __VA_ARGS__)

#define E2D_LOG_FATAL(...) \
    E2D_LOG(::extra2d::LogLevel::Fatal, __VA_ARGS__)

// 简写宏
#define E2D_INFO(...) E2D_LOG_INFO(__VA_ARGS__)
#define E2D_WARN(...) E2D_LOG_WARN(__VA_ARGS__)
#define E2D_ERROR(...) E2D_LOG_ERROR(__VA_ARGS__)
#define E2D_FATAL(...) E2D_LOG_FATAL(__VA_ARGS__)

#ifdef E2D_DEBUG
    #define E2D_DEBUG_LOG(...) E2D_LOG_DEBUG(__VA_ARGS__)
    #define E2D_TRACE(...) E2D_LOG_TRACE(__VA_ARGS__)
#else
    #define E2D_DEBUG_LOG(...)
    #define E2D_TRACE(...)
#endif
