#pragma once
// import_plan — the pure import decision: the destination bank's display name after
// the book's own uniqueness fold, the reminted sample ids and remapped parents, and
// the per-entry land / collapse / rename disposition. Value inputs only; no
// filesystem, no session handle, no host types.

#include <cstddef>
#include <string>
#include <vector>

#include "core/model/bank_book.h"
#include "core/model/slot_map.h"
#include "core/package/package_manifest.h"
#include "core/tracking/origin_ledger.h"

namespace reasampler::package {

// The bank name a package that recorded none (or a blank one) imports under.
inline constexpr const char* kDefaultImportBankName = "Imported bank";

// The prefix every imported sample id is reminted under, so a package's own ids —
// unique only within the project that made them — never enter this index.
inline constexpr const char* kImportIdPrefix = "pkg-";

// Which of the two refusal messages the import owes the user, if either.
//
// Keyed on the LEDGER STATUS ALONE, never on prune's composite blockedByTracking:
// that flag also fires on undecodable rsusage_* keys, which govern which files a
// DELETION may touch. An import deletes nothing and computes no protected set — it
// writes birth records — so an unreadable usage key must not refuse one.
enum class LedgerRefusal { None, Malformed, FutureVersion };

LedgerRefusal importLedgerRefusal(tracking::LedgerStatus status);

// The console-block body for a refusal — a pure (LedgerRefusal, namespace) -> string
// fold, so the wording is assertable without a DAW. `extStateNamespace` is the
// channel-correct namespace (`version::extStateNamespace()`) every recovery line must
// name, so a beta user is never handed the stable spelling. Empty string for None —
// callers only reach this once `importLedgerRefusal` has already returned a refusal.
std::string ledgerRefusalMessage(LedgerRefusal refusal, const std::string& extStateNamespace);

// What one manifest entry does when the import runs.
//  - Land:     write the payload under destFileName and add `sample`.
//  - Collapse: an equal contentHash already lands in this same import, so the payload
//              is NOT written and no entry is added. Writing it and letting
//              BankModel::add collapse the entry would leave the file referenced by
//              nothing — an orphan manufactured by a dedup.
enum class EntryAction { Land, Collapse };

struct PlannedEntry {
    std::size_t   manifestIndex = 0;
    EntryAction   action = EntryAction::Land;
    std::string   destFileName;     // Land only — a bare name in the bank folder
    model::Sample sample;           // Land only — id, path and parent already remapped
    bool          renamed = false;  // the package's own name was taken, so a fresh one was minted
};

struct ImportPlan {
    std::string bankDisplayName;
    bool        bankNameAdjusted = false;  // the seed was taken, so the name carries a suffix
    std::string seedBankName;              // the seed the probe started from
    std::vector<PlannedEntry> entries;     // one per manifest entry, in manifest order
    model::SlotMap slots;                  // the package's slots over the reminted ids
    int landCount = 0;
    int collapseCount = 0;
    // Two distinct triggers, counted separately (bank-package.md:447 defines the first
    // as THE collision counter; conflating the second into it would misreport a mint
    // that never collided as a collision).
    int collisionRenameCount = 0;  // the package's own name was already taken in the bank folder
    int sanitizeRenameCount = 0;   // the package's name was not spelled the way this tool spells
                                    // a bank file (see spelledLikeABankFile, core/package/CLAUDE.md)
};

// The bank folder an import lands into — the same expression capture uses, so an
// imported file is spelled exactly like a captured one.
std::string bankFolderDir(const std::string& projectDir);

// Decides everything about an import except the bytes. `bankFolderFileNames` are the
// bare names already present in that folder (never overwritten); `uniqueTag` is the
// shell's per-import disambiguator, extended with an ascending counter where one tag
// is not enough. Total: every manifest entry yields exactly one PlannedEntry.
ImportPlan planImport(const PackageManifest& manifest,
                      const BankBook& destination,
                      const std::string& projectDir,
                      const std::vector<std::string>& bankFolderFileNames,
                      const std::string& uniqueTag);

}  // namespace reasampler::package
