#include "logger.hpp"

std::ofstream Logger::log_file;
std::string Logger::log_directory;
std::string Logger::current_date;
std::string Logger::current_filename;
int Logger::keep_days_ = 30;

void Logger::init(const std::string& log_dir, int keep_days)
{
    keep_days_ = keep_days;
    log_directory = log_dir;

    if (!std::filesystem::exists(log_directory)) std::filesystem::create_directories(log_directory);

    current_date = get_today_date();
    open_log_file();
}

void Logger::open_log_file()
{
    current_filename = log_directory + "/" + current_date + ".log";

    if (log_file.is_open()) log_file.close();

    log_file.open(current_filename, std::ios::app);

    if (!log_file.is_open())
    {
        std::cerr << "[Logger] Failed to open log file: " << current_filename << std::endl;
    }
}

void Logger::check_date_rollover()
{
    std::string today = get_today_date();
    if (today != current_date)
    {
        current_date = today;
        open_log_file();
        cleanup_old_logs();
    }
}

void Logger::cleanup_old_logs()
{
    namespace fs = std::filesystem;

    for (auto& entry : fs::directory_iterator(log_directory))
    {
        if (!entry.is_regular_file()) continue;

        auto path = entry.path();
        auto filename = path.filename().string();

        if (filename.size() != 14 || filename.substr(4, 1) != "-" || filename.substr(7, 1) != "-")
            continue;  // 跳过不符合 YYYY-MM-DD.log 的文件

        std::tm file_tm{};
        std::istringstream ss(filename.substr(0, 10));  // YYYY-MM-DD
        ss >> std::get_time(&file_tm, "%Y-%m-%d");

        if (ss.fail()) continue;

        auto file_time = std::chrono::system_clock::from_time_t(std::mktime(&file_tm));
        auto now = std::chrono::system_clock::now();

        auto age = std::chrono::duration_cast<std::chrono::hours>(now - file_time).count() / 24;

        if (age > keep_days_)
        {
            fs::remove(path);
        }
    }
}

std::string Logger::get_time_string()
{
    using namespace std::chrono;

    auto now = system_clock::now();
    auto ms = duration_cast<milliseconds>(now.time_since_epoch()) % 1000;

    std::time_t t = system_clock::to_time_t(now);
    std::tm tm_now = *std::localtime(&t);

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

std::string Logger::get_today_date()
{
    auto now = std::chrono::system_clock::now();
    std::time_t t = std::chrono::system_clock::to_time_t(now);
    std::tm tm_now = *std::localtime(&t);

    std::ostringstream ss;
    ss << std::put_time(&tm_now, "%Y-%m-%d");
    return ss.str();
}

std::string Logger::get_current_time_utc8()
{
    auto now = std::chrono::system_clock::now();
    auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()) % 1000;

    std::time_t t = std::chrono::system_clock::to_time_t(now);
    std::tm tm_now = *std::localtime(&t);

    std::ostringstream ss;
    ss << std::put_time(&tm_now, "%Y%m%d%H%M%S") << std::setw(3) << std::setfill('0') << ms.count();

    return ss.str();
}

void Logger::log(LogLevel level, const std::string& msg)
{
    check_date_rollover();

    std::string level_str;
    switch (level)
    {
        case LogLevel::INFO:
            level_str = "[INFO] ";
            break;
        case LogLevel::WARN:
            level_str = "[WARN] ";
            break;
        case LogLevel::ERROR:
            level_str = "[ERROR]";
            break;
    }

    std::string full_msg = get_time_string() + " " + level_str + " " + msg;

    std::cout << full_msg << std::endl;

    if (log_file.is_open())
    {
        log_file << full_msg << std::endl;
        log_file.flush();
    }
}
