// r8r: rust port of n8n.io
// Initial author: Michael Cochran <mcochran@cochranblock.org>
// Built for: Tanner Woodrum, intended cofounder
// License: Unlicense (public domain dedication, see UNLICENSE)

use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::collections::HashMap;

pub type NodeName = String;
pub type RunIndex = u32;

#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct NodeItem {
    #[serde(default)]
    pub json: Value,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub binary: Option<HashMap<String, BinaryData>>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub error: Option<String>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub paired_item: Option<PairedItem>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BinaryData {
    pub mime_type: String,
    pub file_name: Option<String>,
    pub data: Vec<u8>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PairedItem {
    pub item: u32,
    pub input: Option<u8>,
}

pub type NodeOutput = Vec<Vec<NodeItem>>;

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum ConnectionKind {
    Main,
    Error,
    AiTool,
    AiMemory,
    AiLanguageModel,
}

impl Default for ConnectionKind {
    fn default() -> Self { Self::Main }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Edge {
    pub from: NodeName,
    pub to: NodeName,
    #[serde(default)]
    pub kind: ConnectionKind,
    #[serde(default)]
    pub from_index: u8,
    #[serde(default)]
    pub to_index: u8,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum OnError {
    StopWorkflow,
    ContinueRegularOutput,
    ContinueErrorOutput,
}

impl Default for OnError {
    fn default() -> Self { Self::StopWorkflow }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NodeDef {
    pub name: NodeName,
    #[serde(rename = "type")]
    pub type_name: String,
    #[serde(default)]
    pub credentials: Option<String>,
    #[serde(default)]
    pub parameters: HashMap<String, Value>,
    #[serde(default)]
    pub continue_on_fail: bool,
    #[serde(default)]
    pub on_error: OnError,
    #[serde(default = "default_retry")]
    pub max_tries: u8,
}

fn default_retry() -> u8 { 1 }

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PropertyDef {
    pub name: &'static str,
    pub display_name: &'static str,
    pub kind: PropertyKind,
    pub required: bool,
    pub default: Option<&'static str>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum PropertyKind {
    String,
    Number,
    Boolean,
    Json,
    DateTime,
    Color,
    Code,
    Notice,
    Options,
    MultiOptions,
    Collection,
    FixedCollection,
    ResourceLocator,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CredentialRef {
    pub name: &'static str,
    pub required: bool,
}

#[derive(Debug, Clone, Serialize)]
pub struct NodeMetadata {
    pub name: &'static str,
    pub display_name: &'static str,
    pub version: &'static [u32],
    pub group: &'static [&'static str],
    pub description: &'static str,
    pub inputs: u8,
    pub outputs: u8,
    pub properties: &'static [PropertyDef],
    pub credentials: &'static [CredentialRef],
}
