#pragma once
#ifndef LOGGER_H
#define LOGGER_H

// C++ 标准库版本判断
#if __cplusplus >= 202002L && defined(USE_STD_FORMAT)
// C++20 或更高版本
#include <format>
namespace LoggerFormatNS = std;
#else
#include <fmt/core.h>   // 仅基础格式化
#include <fmt/format.h> // 完整功能
namespace LoggerFormatNS = fmt;
#endif

#include <string>
#include <memory>
#include <functional>
#include <iostream>
#include <any>

// 用于支持 << 流式传递打印日志
// LoggerStream.h
#include <sstream>
#include <string>
#include <functional>


// 日志打印等级
enum class LogLevel : int
{
    trace,
    debug,
    info,
    warning,
    error,
    critical,
    off
};
// 日志打印的颜色模式（如黑白或彩色）
enum class LogColorMode : int
{
    automatic,
    always,
    never
};

class LoggerInterface; // 前置声明
class Logger;
// 辅助类：流式日志打印
class LoggerStream
{
public:
    LoggerStream(LoggerInterface *logger, std::function<void(const std::string &)> log_func)
        : logger(logger), logFunc(log_func) {}

    // 允许移动
    LoggerStream(LoggerStream &&) noexcept = default;
    LoggerStream &operator=(LoggerStream &&) noexcept = default;

    // 禁止拷贝
    LoggerStream(const LoggerStream &) = delete;
    LoggerStream &operator=(const LoggerStream &) = delete;

    template <typename T>
    LoggerStream &operator<<(const T &value)
    {
        ss << value;
        return *this;
    }

    ~LoggerStream()
    {
        logFunc(ss.str());
    }

private:
    LoggerInterface *logger;
    std::function<void(const std::string &)> logFunc;
    std::stringstream ss;
};

//class FormatterInterface
//{
//public:
//    virtual ~FormatterInterface() = default;
//    virtual std::string format(const std::string& fmt, ...) = 0;
//};
//class DefaultFormatter : public FormatterInterface
//{
//public:
//    std::string format(const std::string& fmt, ...) override {
//        va_list args;
//        va_start(args, fmt);
//        std::string formatted = LoggerFormatNS::vformat(fmt, fmt::make_format_args(args));
//        va_end(args);
//        return formatted;
//    }
//};


class LoggerSinkInterface {
protected:
    std::string m_pattern;
    LogLevel m_level;
    friend class Logger;
    virtual std::any getBaseSink() = 0;
public:
    virtual ~LoggerSinkInterface() = default;
    virtual void flush() noexcept(false) = 0;
    virtual void setPattern(const std::string& pattern) = 0;
    virtual std::string pattern() const = 0;
    virtual void setLevel(LogLevel level) = 0;
    virtual LogLevel level() const = 0;
};

// 预留了两种打印方法的 Sink 实现，要求每个日志系统都要实现这两种 Sink
// 也可以自定义更多 Sink 实现类
class ConsoleLoggerSink : public LoggerSinkInterface {
protected:
    virtual std::any getBaseSink();
    class Impl;
    std::unique_ptr<Impl> pImpl;
    LogColorMode m_colorMode;
#ifdef _WIN32
    typedef std::uint16_t LogColor;
#else
    typedef std::string_view LogColor;
#endif
    LogColor m_color;
public:
    virtual void flush() noexcept(false);
    virtual void setPattern(const std::string& pattern);
    virtual std::string pattern() const;
    virtual void setLevel(LogLevel level);
    virtual LogLevel level() const;
    explicit ConsoleLoggerSink(const std::string& name, LogColorMode colorMode = LogColorMode::automatic);
    void setColorMode(LogColorMode colorMode);
    void setColor(LogLevel level, LogColor colorCode);
    //LogColorMode getColorMode() const;
    //std::string_view getColor(LogLevel level) const;
};

class FileLoggerSink : public LoggerSinkInterface {
protected:
    virtual std::any getBaseSink();
    class Impl;
    std::unique_ptr<Impl> pImpl;
public:
    struct FileEventHandler {
        std::function<void(const std::string& filename)> beforeOpen = nullptr;
        std::function<void(const std::string& filename, std::FILE* fileStream)> afterOpen = nullptr;
        std::function<void(const std::string& filename, std::FILE* fileStream)> beforeClose = nullptr;
        std::function<void(const std::string& filename)> afterClose = nullptr;
    };
    explicit FileLoggerSink(const std::string& name, bool truncate = false, FileEventHandler eventHandler = FileEventHandler());
    virtual void flush() noexcept(false) = 0;
    virtual void setPattern(const std::string& pattern);
    virtual std::string pattern() const;
    virtual void setLevel(LogLevel level);
    virtual LogLevel level() const;
};

// 日志打印器接口
class LoggerInterface
{
public:
    virtual ~LoggerInterface() = default;
    virtual void setLevel(LogLevel level) noexcept(false) = 0;
    virtual void setGlobalLevel(LogLevel level) noexcept(false) = 0;
    virtual LogLevel level() const noexcept = 0;
    virtual LoggerStream trace() noexcept = 0;
    virtual LoggerStream debug() noexcept = 0;
    virtual LoggerStream info() noexcept = 0;
    virtual LoggerStream warning() noexcept = 0;
    virtual LoggerStream error() noexcept = 0;
    virtual LoggerStream critical() noexcept = 0;
    virtual void trace(const std::string &msg) noexcept = 0;
    virtual void debug(const std::string &msg) noexcept = 0;
    virtual void info(const std::string &msg) noexcept = 0;
    virtual void warning(const std::string &msg) noexcept = 0;
    virtual void error(const std::string &msg) noexcept = 0;
    virtual void critical(const std::string &msg) noexcept = 0;
    // fmt + args
    template <typename... Args>
    void trace(const std::string &fmt, Args &&...args) noexcept {
        _loggerHelper(&LoggerInterface::trace, fmt, std::forward<Args>(args)...);
    }
    template <typename... Args>
    void debug(const std::string &fmt, Args &&...args) noexcept {
        _loggerHelper(&LoggerInterface::debug, fmt, std::forward<Args>(args)...);
    }
    template <typename... Args>
    void info(const std::string &fmt, Args &&...args) noexcept {
        _loggerHelper(&LoggerInterface::info, fmt, std::forward<Args>(args)...);
    }
    template <typename... Args>
    void warning(const std::string &fmt, Args &&...args) noexcept {
        _loggerHelper(&LoggerInterface::warning, fmt, std::forward<Args>(args)...);
    }
    template <typename... Args>
    void error(const std::string &fmt, Args &&...args) noexcept {
        _loggerHelper(&LoggerInterface::error, fmt, std::forward<Args>(args)...);
    }
    template <typename... Args>
    void critical(const std::string &fmt, Args &&...args) noexcept {
        _loggerHelper(&LoggerInterface::critical, fmt, std::forward<Args>(args)...);
    }

private:
    template <typename... Args>
    void _loggerHelper(void (LoggerInterface::*func)(const std::string &), const std::string &fmt, Args &&...args) noexcept {
        std::string formattedMsg = LoggerFormatNS::format(fmt, std::forward<Args>(args)...);
        // 处理后交给具体的日志实现
        (this->*func)(formattedMsg);
    }
};

// 错误码
typedef int LoggerErrorCodeType;
enum class LoggerErrorCode : LoggerErrorCodeType
{
    OK = 0,
    Unknown = 1,
    SinkNotInitialized = 2,
    PatternSetFailed = 3,
};

// 自定义日志抛出的错误
class LoggerException : public std::exception
{
private:
    std::string msg;
    LoggerErrorCode eCode;
public:
    explicit LoggerException(LoggerErrorCode code, const std::string& message) : std::exception(message.c_str()), msg(message), eCode(code) {}
    char const* what() const override {
        return this->msg.c_str();
    }
    LoggerErrorCode code() const {
        return this->eCode;
    }
    std::string toString() const {
        return msg;
    }
    LoggerErrorCodeType toLoggerErrorCodeType() const {
        return static_cast<LoggerErrorCodeType>(eCode);
    }
    operator std::string() const {
        return msg;
    }
    operator LoggerErrorCode() const {
        return eCode;
    }
    operator LoggerErrorCodeType() const {
        return static_cast<LoggerErrorCodeType>(eCode);
    }
};

// 日志打印器
class Logger : public LoggerInterface
{
private:
    class LoggerImpl;
    std::unique_ptr<LoggerImpl> pImpl;

public:
    // 默认构造：仅使用ConsoleLoggerSink
    explicit Logger(const std::string &name);
    // 带有自定义 Sink 列表的构造函数
    template <typename SinksIterator>
    explicit Logger(const std::string &name, SinksIterator&& sinksBegin, SinksIterator&& sinksEnd);
    explicit Logger(const std::string &name, std::vector<std::shared_ptr<LoggerSinkInterface>> sinks)
        : Logger(name, sinks.begin(), sinks.end()) {}
    ~Logger();
    void setGlobalLevel(LogLevel level) noexcept(false) override;
    void setLevel(LogLevel level) noexcept(false) override;
    LogLevel level() const noexcept override;
    // 流式日志打印
    LoggerStream trace() noexcept override;
    LoggerStream debug() noexcept override;
    LoggerStream info() noexcept override;
    LoggerStream warning() noexcept override;
    LoggerStream error() noexcept override;
    LoggerStream critical() noexcept override;
    void trace(const std::string &msg) noexcept override;
    void debug(const std::string &msg) noexcept override;
    void info(const std::string &msg) noexcept override;
    void warning(const std::string &msg) noexcept override;
    void error(const std::string &msg) noexcept override;
    void critical(const std::string &msg) noexcept override;

    // fmt + args
    template <typename... Args>
    void trace(const std::string& fmt, Args &&...args) noexcept {
        _loggerHelper(&LoggerInterface::trace, fmt, std::forward<Args>(args)...);
    }
    template <typename... Args>
    void debug(const std::string& fmt, Args &&...args) noexcept {
        _loggerHelper(&LoggerInterface::debug, fmt, std::forward<Args>(args)...);
    }
    template <typename... Args>
    void info(const std::string& fmt, Args &&...args) noexcept {
        _loggerHelper(&LoggerInterface::info, fmt, std::forward<Args>(args)...);
    }
    template <typename... Args>
    void warning(const std::string& fmt, Args &&...args) noexcept {
        _loggerHelper(&LoggerInterface::warning, fmt, std::forward<Args>(args)...);
    }
    template <typename... Args>
    void error(const std::string& fmt, Args &&...args) noexcept {
        _loggerHelper(&LoggerInterface::error, fmt, std::forward<Args>(args)...);
    }
    template <typename... Args>
    void critical(const std::string& fmt, Args &&...args) noexcept {
        _loggerHelper(&LoggerInterface::critical, fmt, std::forward<Args>(args)...);
    }

private:
    template <typename... Args>
    void _loggerHelper(void (LoggerInterface::* func)(const std::string&), const std::string& fmt, Args &&...args) noexcept {
        std::string formattedMsg = LoggerFormatNS::format(fmt, std::forward<Args>(args)...);
        // 处理后交给具体的日志实现
        (this->*func)(formattedMsg);
    }

};


#endif // !LOGGER_H

