// core/Logger.h
#pragma once
#include <string>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <chrono>
#include <mutex>
#include <windows.h>

enum class LogLevel { Debug, Info, Warning, Error, Fatal };

#define LOG_D(msg) Logger::Log(LogLevel::Debug,    CURRENT_MODULE, __func__, msg)
#define LOG_I(msg) Logger::Log(LogLevel::Info,     CURRENT_MODULE, __func__, msg)
#define LOG_W(msg) Logger::Log(LogLevel::Warning,  CURRENT_MODULE, __func__, msg)
#define LOG_E(msg) Logger::Log(LogLevel::Error,    CURRENT_MODULE, __func__, msg)
#define LOG_F(msg) Logger::Log(LogLevel::Fatal,    CURRENT_MODULE, __func__, msg)

class Logger
{
    static std::mutex mtx;

    static std::string GetTime()
    {
        auto now = std::chrono::system_clock::now();
        auto tt = std::chrono::system_clock::to_time_t(now);
        auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()) % 1000;

        tm local{};
        localtime_s(&local, &tt); 

        std::ostringstream oss;
        oss << std::put_time(&local, "%Y-%m-%d %H:%M:%S")
            << '.' << std::setfill('0') << std::setw(3) << ms.count();
        return oss.str();
    }

    static char LevelChar(LogLevel lv)
    {
        switch (lv)
        {
        case LogLevel::Debug:   return 'D';
        case LogLevel::Info:    return 'I';
        case LogLevel::Warning: return 'W';
        case LogLevel::Error:   return 'E';
        case LogLevel::Fatal:   return 'F';
        default:                return '?';
        }
    }

public:
    template<typename... Args>
    static void Log(LogLevel level, const char* module, const char* func, const std::string& message)
    {
        std::lock_guard<std::mutex> lock(mtx);
        std::ostringstream oss;
        oss << "[" << GetTime() << "] "
            << std::left << std::setw(40) << (std::string(module) + "::" + func + "()")
            << LevelChar(level) << " : " << message;
        std::cout << oss.str() << std::endl;
        OutputDebugStringA((oss.str() + "\n").c_str());
    }
};