#pragma once

#include <chrono>
#include <ctime>
#include <iomanip>
#include <sstream>
#include <string>

namespace ta::foundation::time
{
    [[nodiscard]] inline std::tm local_time(const std::time_t value) noexcept
    {
        std::tm result{};
#if defined(_WIN32)
        localtime_s(&result, &value);
#else
        localtime_r(&value, &result);
#endif
        return result;
    }

    template <typename Character>
    [[nodiscard]] std::basic_string<Character> format_local_timestamp(
        const std::chrono::system_clock::time_point point,
        const Character* format,
        const Character millisecond_separator)
    {
        const auto milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(
            point.time_since_epoch()) % 1000;
        const std::time_t value = std::chrono::system_clock::to_time_t(point);
        const std::tm local = local_time(value);

        std::basic_ostringstream<Character> stream;
        stream << std::put_time(&local, format)
               << millisecond_separator
               << std::setfill(static_cast<Character>('0'))
               << std::setw(3)
               << milliseconds.count();
        return stream.str();
    }
}
