#pragma once

#include <cstddef>
#include <cstdint>
#include <filesystem>
#include <string>
#include <vector>

namespace ta::foundation::logger
{
    enum class Level : std::uint8_t
    {
        Path,
        Info,
        Warning,
        Error,
        Fatal
    };

    struct Entry final
    {
        std::uint64_t sequence = 0;
        Level level = Level::Info;
        std::uint64_t thread_id = 0;
        std::string timestamp;
        std::string channel;
        std::string message;
    };

    class Sink
    {
    public:
        virtual ~Sink() = default;
        virtual void write(const Entry& entry) = 0;
    };

    // The caller owns the sink and must detach it before destruction.
    void set_sink(Sink* sink) noexcept;

    // Persistent output is appended to the supplied path. At 2 MiB it rotates
    // to one .previous backup. Existing in-memory entries are written on open.
    [[nodiscard]] bool set_file_output(const std::filesystem::path& path);
    void close_file_output();
    [[nodiscard]] std::filesystem::path file_output_path();

    void trace(std::string msg);
    void info(std::string msg);
    void warn(std::string msg);
    void error(std::string msg);
    void fatal(std::string msg);

    // Categorized entries use a stable channel name such as RUNTIME, STORAGE,
    // RESOURCE, CONFIG, GAME or UI. One-argument overloads use GENERAL.
    void trace(std::string channel, std::string msg);
    void info(std::string channel, std::string msg);
    void warn(std::string channel, std::string msg);
    void error(std::string channel, std::string msg);
    void fatal(std::string channel, std::string msg);

    // Structured execution-path entry. The trace id correlates asynchronous
    // UI submission, command routing, module consumption and final result.
    void path(std::uint64_t trace_id,
              std::string component,
              std::string stage,
              std::string detail = {});

    [[nodiscard]] std::vector<Entry> snapshot(std::size_t max_entries = 0);
    void clear_history();

    // Save the current in-memory history beside the persistent log file.
    [[nodiscard]] bool save_history();
    [[nodiscard]] std::filesystem::path history_snapshot_path();

    [[nodiscard]] const char* level_name(Level level) noexcept;
}
