//! Story-Lifecycle: Ink-Skript in den Story-Slot laden und schrittweise
//! treiben. Frontend-agnostisch — anders als in irl3d, wo `StoryState`
//! direkt in UI-Panels gegossen wurde, konsumiert hier der Aufrufer
//! (CLI-REPL jetzt, Panel-UI später) den Zustand selbst.
//!
//! Tags eines Schritts werden als `Vec<String>` zurückgegeben — der
//! Aufrufer entscheidet, ob/wie er sie via `signals::dispatch` weiterreicht
//! (vermeidet den Modul-Zyklus signals → story_ctrl → signals).

use crate::engine::assets;
use crate::engine::game::ActionCtx;
use crate::engine::ink::{Story, StoryState};

/// Lädt ein Ink-Skript (Pfad relativ zu `assets/interactions/`) in den
/// Story-Slot. Der erste Schritt passiert noch nicht — das Frontend ruft
/// dafür `advance(None, …)`.
pub fn start(script: &str, ctx: &mut ActionCtx) {
    let path = assets::path(&format!("assets/interactions/{script}"));
    match Story::load(&path, ctx.kv) {
        Ok(story) => *ctx.story = Some(story),
        // Kaputtes/fehlendes Skript darf das Spiel nicht crashen: den Slot
        // leer lassen (kein Dialog öffnet) und den Fehler nach stderr melden.
        Err(msg)  => eprintln!("[start_ink] {msg}"),
    }
}

/// Treibt die laufende Story einen Schritt weiter. `sel` ist die
/// Choice-Auswahl bzw. `None` beim ersten Schritt oder Text-Weiterklicken.
/// Bei `End` wird der Story-Slot geleert. Rückgabe: neuer Zustand (oder
/// `None` wenn gar keine Story läuft) plus Tags zum Dispatchen.
pub fn advance(sel: Option<usize>, ctx: &mut ActionCtx) -> (Option<StoryState>, Vec<String>) {
    let Some(st) = ctx.story.as_mut() else { return (None, Vec::new()); };
    if let Some(i) = sel { st.choose(i); }
    let state = st.cont(ctx.kv);
    let tags = st.take_tags();
    if matches!(state, StoryState::End) { *ctx.story = None; }
    (Some(state), tags)
}
