//! IR data model — mirrors `cores/mizan-python/src/mizan_core/ir.py` 1:1.
//!
//! The IR is the contract. Backends emit it; codegen consumes it. The Rust
//! side produces byte-equivalent KDL to the Python emitter against the same
//! function registry.

/// A named type that appears in the IR's `type "<Name>" { ... }` section.
#[derive(Debug, Clone)]
pub enum NamedType {
    /// `type "X" { struct { field ... } }` — a Pydantic-model-shaped record.
    Struct(Vec<StructField>),
    /// `type "X" { alias { <type-child> } }` — a named wrapper around an
    /// inline type shape, e.g. `userOrdersOutput = list[OrderOutput]`.
    Alias(TypeShape),
    /// `type "X" { enum "A" "B" ... }` — a string-literal enum.
    Enum(Vec<&'static str>),
}

/// The set of in-place type shapes referenced from struct fields, function
/// inputs/outputs, and alias bodies.
#[derive(Debug, Clone)]
pub enum TypeShape {
    Primitive(Primitive),
    Ref(&'static str),
    List(Box<TypeShape>),
    Optional(Box<TypeShape>),
    Enum(Vec<&'static str>),
    Union(Vec<TypeShape>),
}

#[derive(Debug, Clone, Copy)]
pub enum Primitive {
    Integer,
    Number,
    Boolean,
    String,
}

impl Primitive {
    pub fn name(self) -> &'static str {
        match self {
            Primitive::Integer => "integer",
            Primitive::Number => "number",
            Primitive::Boolean => "boolean",
            Primitive::String => "string",
        }
    }
}

#[derive(Debug, Clone)]
pub struct StructField {
    pub name: &'static str,
    pub required: bool,
    pub default: Option<DefaultValue>,
    pub shape: TypeShape,
}

#[derive(Debug, Clone)]
pub enum DefaultValue {
    Integer(i64),
    Number(f64),
    Boolean(bool),
    String(&'static str),
    Null,
}

/// One descriptor of what a mutation `affects`. Mirrors Python's
/// `_normalize_affects` shape — either a named context or a named function.
#[derive(Debug, Clone)]
pub enum AffectTarget {
    Context(&'static str),
    Function {
        name: &'static str,
        context: Option<&'static str>,
    },
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Transport {
    Http,
    Websocket,
    Both,
}

impl Transport {
    pub fn name(self) -> &'static str {
        match self {
            Transport::Http => "http",
            Transport::Websocket => "websocket",
            Transport::Both => "both",
        }
    }
}
