BareGit
#pragma once

#include <cstdint>
#include <filesystem>
#include <string>

#include <mw/error.hpp>

class DataSourceInterface;

/// Published asset directory retained until an edit transaction commits.
struct AssetReplacement
{
    /// Public ID whose directory was replaced.
    std::string public_id;

    /// Private path containing the previous published directory.
    std::filesystem::path previous_directory;
};

/// Published card assets retained until a delete transaction commits.
struct TrashedAssets
{
    /// Public ID whose directory was moved.
    std::string public_id;

    /// Private trash path, empty when no published directory existed.
    std::filesystem::path trash_directory;
};

/// Atomically publish and remove complete card asset directories.
class AssetStore
{
public:
    /// Construct an asset store below the configured private root.
    explicit AssetStore(std::filesystem::path card_storage_root);

    /// Return the canonical published directory for one public ID.
    std::filesystem::path directory(const std::string& public_id) const;

    /// Rename a complete staging directory into its public location.
    mw::E<void> publish(
        const std::filesystem::path& staging_directory,
        const std::string& public_id) const;

    /// Swap a complete staging directory with existing published assets.
    mw::E<AssetReplacement> replace(
        const std::filesystem::path& staging_directory,
        const std::string& public_id,
        std::int64_t previous_revision) const;

    /// Restore the previous assets after a database rollback.
    void restore(const AssetReplacement& replacement) const;

    /// Remove previous assets after the database update commits.
    void finish(const AssetReplacement& replacement) const;

    /// Move published assets to a uniquely named private trash directory.
    mw::E<TrashedAssets> trash(
        const std::string& public_id,
        std::int64_t revision,
        const std::string& suffix) const;

    /// Restore assets after a card-delete transaction rollback.
    void restore(const TrashedAssets& trashed) const;

    /// Permanently remove assets after a card-delete transaction commits.
    void finish(const TrashedAssets& trashed) const;

    /// Remove one precisely identified published directory after rollback.
    void removePublished(const std::string& public_id) const;

    /// Reconcile private transitions and orphaned public directories.
    mw::E<void> reconcile(DataSourceInterface& data_source) const;

private:
    std::filesystem::path published_root_;
};