// shell/package/package_rollback — the files ONE import call has landed, as a
// journal: writes record themselves on success, and rollback() deletes exactly what
// is recorded. The deletion carve-out this satisfies, and the half of it the caller
// still owns, are at package_rollback.cpp's header.

#pragma once

#include <string>
#include <vector>

#include "shell/package/package_io.h"

namespace reasampler {

struct RollbackResult {
    int deletedCount = 0;
    int alreadyAbsentCount = 0;  // vanished between land and rollback — not a failure
    int failedCount = 0;         // locked / permission — recorded, never thrown
    bool refused = false;        // markIndexCommitted() ran: nothing was deleted
};

// Destroying an armed (uncommitted, un-rolled-back) journal is NOT an implicit
// rollback — the caller must call rollback() itself on the failure path it wants
// to undo. That's the fail-safe direction: a journal dropped by an unrelated early
// return leaves the landed files in place rather than silently deleting them.
class LandedFileJournal {
public:
    // Lands one payload at destPath through the exclusive create (which refuses an
    // occupied path outright — a bank-folder file is never overwritten, and collision
    // handling is the import plan's job upstream) and records it on success. An empty
    // payload is refused, per writeFileExclusive. Relative paths are resolved against
    // the process CWD before the write, so the journal's record is always absolute
    // and a later CWD change cannot re-aim the delete. Refused once
    // markIndexCommitted() has run.
    bool writeLandedFile(const std::string& destPath, const PayloadBuffer& payload);

    // Disarms the journal: the index mutation these files back is committed, so they
    // are now referenced bytes and the carve-out no longer covers them. This is the
    // half of prune's discriminator the journal cannot make structural on its own —
    // the import verb MUST call this only AFTER the index write has returned success.
    // Calling it before, then having that write fail, strands the landed files with
    // no index entry and a journal that now refuses to roll them back.
    void markIndexCommitted() { indexCommitted_ = true; }
    bool indexCommitted() const { return indexCommitted_; }

    // Deletes exactly the recorded files and clears the journal, so a second call is
    // a no-op. Hard unlink, not trash: nothing ever referenced these bytes. Refuses
    // (deleting nothing, keeping the record) once markIndexCommitted() has run.
    RollbackResult rollback();

    const std::vector<std::string>& landedPaths() const { return paths_; }
    bool empty() const { return paths_.empty(); }

private:
    std::vector<std::string> paths_;
    bool indexCommitted_ = false;
};

}  // namespace reasampler
