use serde::{Deserialize, Serialize};
use serde_json::Value;

use rrt_runtime::engine::StepCommand;
use rrt_runtime::state::RuntimeState;

use super::ExpectedRuntimeSummary;

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
pub struct FixtureSource {
    pub kind: String,
    #[serde(default)]
    pub description: Option<String>,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct FixtureDocument {
    pub format_version: u32,
    pub fixture_id: String,
    #[serde(default)]
    pub source: FixtureSource,
    pub state: RuntimeState,
    pub state_origin: FixtureStateOrigin,
    #[serde(default)]
    pub commands: Vec<StepCommand>,
    #[serde(default)]
    pub expected_summary: ExpectedRuntimeSummary,
    #[serde(default)]
    pub expected_state_fragment: Option<Value>,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum FixtureStateOrigin {
    Inline,
    SnapshotPath(String),
    SaveSlicePath(String),
    InputPath(String),
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct RawFixtureDocument {
    pub format_version: u32,
    pub fixture_id: String,
    #[serde(default)]
    pub source: FixtureSource,
    #[serde(default)]
    pub state: Option<RuntimeState>,
    #[serde(default)]
    pub state_snapshot_path: Option<String>,
    #[serde(default)]
    pub state_save_slice_path: Option<String>,
    #[serde(default)]
    pub state_input_path: Option<String>,
    #[serde(default)]
    pub commands: Vec<StepCommand>,
    #[serde(default)]
    pub expected_summary: ExpectedRuntimeSummary,
    #[serde(default)]
    pub expected_state_fragment: Option<Value>,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct FixtureValidationReport {
    pub fixture_id: String,
    pub valid: bool,
    pub issue_count: usize,
    pub issues: Vec<String>,
}
