//! Serde deserializer for KDL documents.
//!
//! This module provides [`from_str`] for deserializing Rust types from KDL text.
//!
//! Due to the fact that `serde` was developed with JSON in mind, and the incompatibility
//! between KDL and JSON's data model, not all `serde` concepts apply smoothly to KDL. This
//! leads to the fact that some KDL concepts are inexpressible in terms of `serde` derives
//! and may require manual deserialization.
//!
//! The most notable restriction is the ability to distinguish between *arguments*,
//! *properties* and *child nodes*, as JSON does not have such conception.
//!
//! Due to that the mapping is performed in a best effort manner.
//!
//! # KDL → Serde Data Model Mapping
//!
//! KDL documents are mapped to serde's data model as follows:
//!
//! - A **KDL document** is treated as a **map** (or struct), where each top-level
//!   node name is a key and the node's content is the value.
//! - A **KDL node with no arguments** and no properties/children is treated as
//!   a **boolean flag**.
//! - A **KDL node with only a single argument** and no properties/children is
//!   treated as a **scalar value** (the argument itself).
//! - A **KDL node with multiple arguments** is treated as a **sequence** of those arguments.
//! - A **KDL node with properties** is treated as a **map** of property names to values.
//! - A **KDL node with children** is treated as a **map** (or struct), where child
//!   node names are keys.
//! - A **KDL node with both properties and children** merges them into a single map.
//! - **Repeated node names** at the same level are collected into a **sequence**.
//!
//! # Example
//!
//! ```rust
//! use serde::Deserialize;
//!
//! #[derive(Deserialize, Debug, PartialEq)]
//! struct Config {
//!     name: String,
//!     port: u16,
//!     active: bool
//! }
//!
//! let kdl = r#"
//! name my-app
//! port 8080
//! active
//! "#;
//!
//! let config: Config = kdl::de::from_str(kdl).unwrap();
//! assert_eq!(config, Config { name: "my-app".into(), port: 8080, active: true });
//! ```
//!
//! ## Arguments mapping
//!
//! This library supports three kinds of special renaming for arguments - `#{n}`, `#args`, and `#rest`:
//!
//! - `#{n}`: This is used when you want to access argument at a specific
//!   position. The field name should start with `#`, then follow by the position
//!   of the argument in numerical order starting from 0.
//!
//! ```rust
//! use serde::Deserialize;
//!
//! #[derive(Deserialize, Debug, PartialEq)]
//! struct Config {
//!     server: Server,
//! }
//!
//! #[derive(Deserialize, Debug, PartialEq)]
//! struct Server {
//!     #[serde(rename = "#0")]
//!     name: String,
//!     #[serde(rename = "#1")]
//!     port: u16,
//! }
//!
//! let kdl = r#"
//! server my-app 8080
//! "#;
//!
//! let config: Config = kdl::de::from_str(kdl).unwrap();
//! assert_eq!(config, Config { server: Server { name: "my-app".into(), port: 8080 }});
//! ```
//!
//! - `#args`: This is used when you want to collect *all* the arguments of the node.
//!
//! ```rust
//! use serde::Deserialize;
//!
//! #[derive(Deserialize, Debug, PartialEq)]
//! struct Config {
//!     server: Server,
//! }
//!
//! #[derive(Deserialize, Debug, PartialEq)]
//! struct Server {
//!     #[serde(rename = "#args")]
//!     info: Vec<String>,
//! }
//!
//! let kdl = r#"
//! server my-app "https://example.com"
//! "#;
//!
//! let config: Config = kdl::de::from_str(kdl).unwrap();
//! assert_eq!(config, Config { server: Server { info: Vec::from(["my-app".into(), "https://example.com".into()]) }});
//! ```
//!
//! - `#rest`: This is used when you want to collect everything that wasn't
//!   referenced by an `#{n}` rename.
//!
//! ```rust
//! use serde::Deserialize;
//!
//! #[derive(Deserialize, Debug, PartialEq)]
//! struct Config {
//!     command: Command,
//! }
//!
//! #[derive(Deserialize, Debug, PartialEq)]
//! struct Command {
//!     #[serde(rename = "#0")]
//!     cmd: String,
//!     #[serde(rename = "#rest")]
//!     args: Vec<String>,
//! }
//!
//! let kdl = r#"
//! command frob "https://example.com" x y
//! "#;
//!
//! let config: Config = kdl::de::from_str(kdl).unwrap();
//! assert_eq!(config, Config { command: Command { cmd: "frob".into(), args: vec!["https://example.com".into(), "x".into(), "y".into()]}});
//! ```
//!
//! ## Properties mapping
//!
//! You can use `#@field-name` on a field that will be used for a property.
//!
//! ```rust
//! use serde::Deserialize;
//!
//! #[derive(Deserialize, Debug, PartialEq)]
//! struct Config {
//!     server: Server,
//! }
//!
//! #[derive(Deserialize, Debug, PartialEq)]
//! struct Server {
//!     #[serde(rename = "#0")]
//!     name: String,
//!     #[serde(rename = "#@port")]
//!     port: u16,
//! }
//!
//! let kdl = r#"
//! server my-app port=8080
//! "#;
//!
//! let config: Config = kdl::de::from_str(kdl).unwrap();
//! assert_eq!(config, Config { server: Server { name: "my-app".into(), port: 8080 }});
//! ```
//!
//! ## Types mapping
//!
//! You can extract type annotations for nodes, arguments and properties by
//! using `#type`:
//!
//! ```rust
//! use serde::Deserialize;
//!
//! #[derive(Deserialize, Debug, PartialEq)]
//! struct Config {
//!     server: Server,
//! }
//!
//! #[derive(Deserialize, Debug, PartialEq)]
//! #[serde(rename_all = "kebab-case")]
//! enum ServerKind {
//!     Big,
//!     Small,
//! }
//! #[derive(Deserialize, Debug, PartialEq)]
//! struct Server {
//!     #[serde(rename = "#type")]
//!     server_kind: ServerKind,
//!     #[serde(rename = "#0#type")]
//!     app_type: String,
//!     #[serde(rename = "#@port#type")]
//!     port_type: String,
//! }
//!
//! let kdl = r#"
//! (big)server (cool)my-app port=(internal)8080
//! "#;
//!
//! let config: Config = kdl::de::from_str(kdl).unwrap();
//! assert_eq!(config, Config { server: Server { server_kind: ServerKind::Big, app_type: "cool".into(), port_type: "internal".into() }});
//! ```

use std::borrow::Cow;
use std::sync::Arc;
use std::{fmt, iter};

use miette::{Diagnostic, LabeledSpan, Severity, SourceCode, SourceSpan};
use serde::Deserialize;
use serde::de::value::StringDeserializer;
use serde::de::{self, DeserializeSeed, Deserializer, MapAccess, SeqAccess, Visitor};

use crate::{KdlDiagnostic, KdlDocument, KdlEntry, KdlIdentifier, KdlNode, KdlValue};

/// Errors that can occur during KDL deserialization.
#[derive(Debug, Clone)]
pub struct Error {
    msg: String,
    input: Option<Arc<String>>,
    span: Option<SourceSpan>,
    label: Option<String>,
    diagnostics: Vec<KdlDiagnostic>,
}

impl Error {
    fn new(msg: impl fmt::Display) -> Self {
        Error {
            msg: msg.to_string(),
            input: None,
            span: None,
            label: None,
            diagnostics: Vec::new(),
        }
    }

    /// Gets the source span associated with this deserialization error.
    pub fn span(&self) -> Option<SourceSpan> {
        self.span
    }

    /// Gets this error as a KDL diagnostic, if available.
    pub fn diagnostic(&self) -> Option<KdlDiagnostic> {
        if let Some(diagnostic) = self.diagnostics.first() {
            Some(diagnostic.clone())
        } else {
            Some(KdlDiagnostic {
                input: self.input.clone()?,
                span: self.span?,
                message: Some(self.msg.clone()),
                label: self.label.clone(),
                help: None,
                severity: Severity::Error,
            })
        }
    }

    fn with_input(mut self, input: &Arc<String>) -> Self {
        if self.input.is_none() {
            self.input = Some(input.clone());
        }
        self
    }

    fn with_span(
        mut self,
        input: &Arc<String>,
        span: SourceSpan,
        label: impl Into<String>,
    ) -> Self {
        if self.input.is_none() {
            self.input = Some(input.clone());
        }
        if self.span.is_none() {
            self.span = Some(span);
            self.label = Some(label.into());
        }
        self
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.msg)
    }
}

impl std::error::Error for Error {}

impl Diagnostic for Error {
    fn source_code(&self) -> Option<&dyn SourceCode> {
        self.input.as_ref().map(|input| input as &dyn SourceCode)
    }

    fn severity(&self) -> Option<Severity> {
        Some(Severity::Error)
    }

    fn labels(&self) -> Option<Box<dyn Iterator<Item = LabeledSpan> + '_>> {
        let span = self.span?;
        let label = self.label.clone();
        Some(Box::new(iter::once(LabeledSpan::new_with_span(
            label, span,
        ))))
    }

    fn related<'a>(&'a self) -> Option<Box<dyn Iterator<Item = &'a dyn Diagnostic> + 'a>> {
        if self.diagnostics.is_empty() {
            None
        } else {
            Some(Box::new(
                self.diagnostics.iter().map(|d| d as &dyn Diagnostic),
            ))
        }
    }
}

impl de::Error for Error {
    fn custom<T: fmt::Display>(msg: T) -> Self {
        Error::new(msg)
    }
}

impl From<crate::KdlError> for Error {
    fn from(e: crate::KdlError) -> Self {
        Error {
            msg: e.to_string(),
            input: Some(e.input.clone()),
            span: e.diagnostics.first().map(|diagnostic| diagnostic.span),
            label: e
                .diagnostics
                .first()
                .and_then(|diagnostic| diagnostic.label.clone()),
            diagnostics: e.diagnostics,
        }
    }
}

/// Helper to produce a `StrDeserializer` with our error type.
fn str_deserializer(s: &str) -> de::value::StrDeserializer<'_, Error> {
    de::IntoDeserializer::into_deserializer(s)
}

fn entry_span(entry: &KdlEntry) -> SourceSpan {
    #[cfg(feature = "span")]
    {
        entry.span()
    }
    #[cfg(not(feature = "span"))]
    {
        SourceSpan::from(0..0)
    }
}

fn ident_span(ident: &KdlIdentifier) -> SourceSpan {
    #[cfg(feature = "span")]
    {
        ident.span()
    }
    #[cfg(not(feature = "span"))]
    {
        SourceSpan::from(0..0)
    }
}

fn node_span(node: &KdlNode) -> SourceSpan {
    #[cfg(feature = "span")]
    {
        node.span()
    }
    #[cfg(not(feature = "span"))]
    {
        SourceSpan::from(0..0)
    }
}

/// Deserialize a type from a KDL string.
///
/// # Example
///
/// ```rust
/// use serde::Deserialize;
///
/// #[derive(Deserialize, Debug, PartialEq)]
/// struct Config {
///     name: String,
///     port: u16,
/// }
///
/// let kdl = r#"
/// name my-app
/// port 8080
/// "#;
///
/// let config: Config = kdl::de::from_str(kdl).unwrap();
/// assert_eq!(config, Config { name: "my-app".into(), port: 8080 });
/// ```
pub fn from_str<'a, T>(input: &'a str) -> Result<T, Error>
where
    T: Deserialize<'a>,
{
    let doc = input.parse()?;
    let input = input.to_owned().into();
    let de = DocumentDeserializer {
        doc: &doc,
        input: &input,
    };
    T::deserialize(de).map_err(|err| err.with_input(&input))
}

struct IdentDeserializer<'a> {
    ident: &'a KdlIdentifier,
    input: &'a Arc<String>,
    span: SourceSpan,
}

impl<'de, 'a> de::Deserializer<'de> for IdentDeserializer<'a> {
    type Error = Error;

    fn deserialize_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        self.annotate(visitor.visit_str(self.ident.value()))
    }

    fn deserialize_string<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        self.annotate(visitor.visit_string(self.ident.value().into()))
    }

    fn deserialize_str<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        self.annotate(visitor.visit_str(self.ident.value()))
    }

    fn deserialize_newtype_struct<V: Visitor<'de>>(
        self,
        _name: &'static str,
        visitor: V,
    ) -> Result<V::Value, Self::Error> {
        visitor.visit_newtype_struct(self)
    }

    fn deserialize_enum<V: Visitor<'de>>(
        self,
        _name: &'static str,
        _variants: &'static [&'static str],
        visitor: V,
    ) -> Result<V::Value, Self::Error> {
        self.annotate(visitor.visit_enum(str_deserializer(self.ident.value())))
    }

    serde::forward_to_deserialize_any! {
        bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char
        bytes byte_buf unit unit_struct seq tuple
        tuple_struct map struct option identifier ignored_any
    }
}

impl<'a> IdentDeserializer<'a> {
    fn new(ident: &'a KdlIdentifier, input: &'a Arc<String>) -> Self {
        IdentDeserializer {
            ident,
            input,
            span: ident_span(ident),
        }
    }

    fn annotate<T>(&self, result: Result<T, Error>) -> Result<T, Error> {
        result.map_err(|err| {
            err.with_span(
                self.input,
                self.span,
                "while deserializing this KDL identifier",
            )
        })
    }
}

struct ValueDeserializer<'a> {
    value: &'a KdlValue,
    input: &'a Arc<String>,
    span: SourceSpan,
}

impl<'a> ValueDeserializer<'a> {
    fn new(entry: &'a KdlEntry, input: &'a Arc<String>) -> Self {
        ValueDeserializer {
            value: entry.value(),
            input,
            span: entry_span(entry),
        }
    }

    fn annotate<T>(&self, result: Result<T, Error>) -> Result<T, Error> {
        result.map_err(|err| {
            err.with_span(self.input, self.span, "while deserializing this KDL value")
        })
    }
}

impl<'de, 'a> de::Deserializer<'de> for ValueDeserializer<'a> {
    type Error = Error;

    fn deserialize_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        match self.value {
            KdlValue::String(s) => self.annotate(visitor.visit_str(s)),
            KdlValue::Integer(n) => {
                if let Ok(i) = i64::try_from(*n) {
                    self.annotate(visitor.visit_i64(i))
                } else if let Ok(u) = u64::try_from(*n) {
                    self.annotate(visitor.visit_u64(u))
                } else {
                    self.annotate(visitor.visit_i128(*n))
                }
            }
            KdlValue::Float(f) => self.annotate(visitor.visit_f64(*f)),
            KdlValue::Bool(b) => self.annotate(visitor.visit_bool(*b)),
            KdlValue::Null => self.annotate(visitor.visit_unit()),
        }
    }

    fn deserialize_option<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        match self.value {
            KdlValue::Null => self.annotate(visitor.visit_none()),
            _ => visitor.visit_some(self),
        }
    }

    fn deserialize_newtype_struct<V: Visitor<'de>>(
        self,
        _name: &'static str,
        visitor: V,
    ) -> Result<V::Value, Self::Error> {
        visitor.visit_newtype_struct(self)
    }

    fn deserialize_enum<V: Visitor<'de>>(
        self,
        _name: &'static str,
        _variants: &'static [&'static str],
        visitor: V,
    ) -> Result<V::Value, Self::Error> {
        self.annotate(match self.value {
            KdlValue::String(s) => visitor.visit_enum(str_deserializer(s.as_str())),
            _ => Err(Error::new("expected a string for unit enum variant")),
        })
    }

    fn deserialize_string<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        match self.value {
            KdlValue::String(s) => self.annotate(visitor.visit_string(s.clone())),
            _ => self.deserialize_any(visitor),
        }
    }

    fn deserialize_str<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        match self.value {
            KdlValue::String(s) => self.annotate(visitor.visit_str(s)),
            _ => self.deserialize_any(visitor),
        }
    }

    serde::forward_to_deserialize_any! {
        bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char
        bytes byte_buf unit unit_struct seq tuple
        tuple_struct map struct identifier ignored_any
    }
}

struct DocumentDeserializer<'a> {
    doc: &'a KdlDocument,
    input: &'a Arc<String>,
}

impl<'de, 'a> de::Deserializer<'de> for DocumentDeserializer<'a> {
    type Error = Error;

    fn deserialize_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        self.deserialize_map(visitor)
    }

    fn deserialize_map<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        visitor.visit_map(DocumentMapAccess::new(self.doc, self.input))
    }

    fn deserialize_struct<V: Visitor<'de>>(
        self,
        _name: &'static str,
        _fields: &'static [&'static str],
        visitor: V,
    ) -> Result<V::Value, Self::Error> {
        self.deserialize_map(visitor)
    }

    fn deserialize_seq<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        visitor.visit_seq(NodeListSeqAccess {
            iter: self.doc.nodes().iter(),
            input: self.input,
        })
    }

    fn deserialize_option<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        if self.doc.nodes().is_empty() {
            visitor.visit_none()
        } else {
            visitor.visit_some(self)
        }
    }

    fn deserialize_newtype_struct<V: Visitor<'de>>(
        self,
        _name: &'static str,
        visitor: V,
    ) -> Result<V::Value, Self::Error> {
        visitor.visit_newtype_struct(self)
    }

    fn deserialize_unit<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        visitor.visit_unit()
    }

    fn deserialize_unit_struct<V: Visitor<'de>>(
        self,
        _name: &'static str,
        visitor: V,
    ) -> Result<V::Value, Self::Error> {
        visitor.visit_unit()
    }

    fn deserialize_enum<V: Visitor<'de>>(
        self,
        _name: &'static str,
        _variants: &'static [&'static str],
        visitor: V,
    ) -> Result<V::Value, Self::Error> {
        // For enums at document level, treat as a single-node document where
        // the node name is the variant.
        let nodes = self.doc.nodes();
        if nodes.len() == 1 {
            visitor.visit_enum(NodeEnumAccess {
                node: &nodes[0],
                input: self.input,
            })
        } else {
            Err(Error::new(
                "expected exactly one node for enum deserialization",
            ))
            .map_err(|err| err.with_input(self.input))
        }
    }

    serde::forward_to_deserialize_any! {
        bool i8 i16 i32
        i64 i128 u8 u16
        u32 u64 u128 f32
        f64 char str string
        bytes byte_buf tuple
        tuple_struct identifier ignored_any
    }
}

/// Groups nodes by name, producing deduplicated keys. Nodes that share a name
/// are collected into a Vec so they can be deserialized as sequences.
struct DocumentMapAccess<'a> {
    /// Ordered unique keys (node names in first-seen order).
    keys: Vec<&'a str>,

    /// All nodes grouped by name, preserving order within each group.
    groups: std::collections::HashMap<&'a str, Vec<&'a KdlNode>>,

    /// Current index into `keys`.
    idx: usize,

    /// The input string.
    input: &'a Arc<String>,
}

impl<'a> DocumentMapAccess<'a> {
    fn new(doc: &'a KdlDocument, input: &'a Arc<String>) -> Self {
        let mut keys = Vec::new();
        let mut groups: std::collections::HashMap<&'a str, Vec<&'a KdlNode>> =
            std::collections::HashMap::new();
        for node in doc.nodes() {
            let name = node.name().value();
            if !groups.contains_key(name) {
                keys.push(name);
            }
            groups.entry(name).or_default().push(node);
        }
        DocumentMapAccess {
            keys,
            groups,
            idx: 0,
            input,
        }
    }
}

impl<'de, 'a> MapAccess<'de> for DocumentMapAccess<'a> {
    type Error = Error;

    fn next_key_seed<K: DeserializeSeed<'de>>(
        &mut self,
        seed: K,
    ) -> Result<Option<K::Value>, Self::Error> {
        if self.idx >= self.keys.len() {
            return Ok(None);
        }
        let key = self.keys[self.idx];
        seed.deserialize(str_deserializer(key)).map(Some)
    }

    fn next_value_seed<V: DeserializeSeed<'de>>(
        &mut self,
        seed: V,
    ) -> Result<V::Value, Self::Error> {
        let key = self.keys[self.idx];
        self.idx += 1;
        let nodes = self.groups.get(key).unwrap();
        if nodes.len() == 1 {
            seed.deserialize(NodeDeserializer {
                node: nodes[0],
                input: self.input,
            })
        } else {
            // Multiple nodes with same name → sequence
            seed.deserialize(NodeGroupDeserializer {
                nodes,
                input: self.input,
            })
        }
    }
}

struct NodeDeserializer<'a> {
    node: &'a KdlNode,
    input: &'a Arc<String>,
}

impl<'a> NodeDeserializer<'a> {
    fn args(&self) -> Vec<&'a KdlEntry> {
        self.node
            .entries()
            .iter()
            .filter(|e| e.name().is_none())
            .collect()
    }

    fn props(&self) -> Vec<&'a KdlEntry> {
        self.node
            .entries()
            .iter()
            .filter(|e| e.name().is_some())
            .collect()
    }

    /// Returns true if this node has only a single argument and nothing else.
    fn is_scalar(&self) -> bool {
        let args = self.args();
        let props = self.props();
        args.len() == 1 && props.is_empty() && self.node.children().is_none()
    }

    /// Returns true if this node is "empty" (no args, no props, no children).
    fn is_empty(&self) -> bool {
        self.node.entries().is_empty() && self.node.children().is_none()
    }
}

impl<'de, 'a> de::Deserializer<'de> for NodeDeserializer<'a> {
    type Error = Error;

    fn deserialize_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        if self.is_empty() {
            // Node with no data → bool flag
            return visitor.visit_bool(true);
        }
        if self.is_scalar() {
            // Single argument → deserialize as scalar
            let entry = self.args()[0];
            return ValueDeserializer::new(entry, self.input).deserialize_any(visitor);
        }

        let args = self.args();
        let props = self.props();
        let has_children = self.node.children().is_some();

        if !args.is_empty() && props.is_empty() && !has_children {
            // Only positional args → sequence
            return visitor.visit_seq(ArgSeqAccess {
                iter: args.into_iter(),
                input: self.input,
            });
        }

        // Has properties and/or children → map
        self.deserialize_map(visitor)
    }

    fn deserialize_bool<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        if self.is_scalar() {
            ValueDeserializer::new(self.args()[0], self.input).deserialize_any(visitor)
        } else if self.is_empty() {
            visitor.visit_bool(true)
        } else {
            Err(Error::new("expected a boolean value")).map_err(|err| {
                err.with_span(
                    self.input,
                    node_span(self.node),
                    "while deserializing this KDL node",
                )
            })
        }
    }

    fn deserialize_i8<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        self.deserialize_scalar(visitor)
    }
    fn deserialize_i16<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        self.deserialize_scalar(visitor)
    }
    fn deserialize_i32<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        self.deserialize_scalar(visitor)
    }
    fn deserialize_i64<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        self.deserialize_scalar(visitor)
    }
    fn deserialize_i128<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        self.deserialize_scalar(visitor)
    }
    fn deserialize_u8<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        self.deserialize_scalar(visitor)
    }
    fn deserialize_u16<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        self.deserialize_scalar(visitor)
    }
    fn deserialize_u32<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        self.deserialize_scalar(visitor)
    }
    fn deserialize_u64<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        self.deserialize_scalar(visitor)
    }
    fn deserialize_u128<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        self.deserialize_scalar(visitor)
    }
    fn deserialize_f32<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        self.deserialize_scalar(visitor)
    }
    fn deserialize_f64<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        self.deserialize_scalar(visitor)
    }
    fn deserialize_char<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        self.deserialize_scalar(visitor)
    }
    fn deserialize_str<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        self.deserialize_scalar(visitor)
    }
    fn deserialize_string<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        self.deserialize_scalar(visitor)
    }
    fn deserialize_bytes<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        self.deserialize_scalar(visitor)
    }
    fn deserialize_byte_buf<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        self.deserialize_scalar(visitor)
    }

    fn deserialize_option<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        if self.is_empty() {
            visitor.visit_none()
        } else if self.is_scalar() {
            let val = self.args()[0].value();
            if matches!(val, KdlValue::Null) {
                visitor.visit_none()
            } else {
                visitor.visit_some(self)
            }
        } else {
            visitor.visit_some(self)
        }
    }

    fn deserialize_unit<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        visitor.visit_unit()
    }

    fn deserialize_unit_struct<V: Visitor<'de>>(
        self,
        _name: &'static str,
        visitor: V,
    ) -> Result<V::Value, Self::Error> {
        visitor.visit_unit()
    }

    fn deserialize_newtype_struct<V: Visitor<'de>>(
        self,
        _name: &'static str,
        visitor: V,
    ) -> Result<V::Value, Self::Error> {
        visitor.visit_newtype_struct(self)
    }

    fn deserialize_seq<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        let args = self.args();

        if !args.is_empty() && self.node.children().is_none() {
            // Arguments → sequence
            visitor.visit_seq(ArgSeqAccess {
                iter: args.into_iter(),
                input: self.input,
            })
        } else if let Some(children) = self.node.children() {
            // Children → sequence of nodes
            visitor.visit_seq(NodeListSeqAccess {
                iter: children.nodes().iter(),
                input: self.input,
            })
        } else {
            // Empty → empty sequence
            visitor.visit_seq(ArgSeqAccess {
                iter: Vec::new().into_iter(),
                input: self.input,
            })
        }
    }

    fn deserialize_tuple<V: Visitor<'de>>(
        self,
        _len: usize,
        visitor: V,
    ) -> Result<V::Value, Self::Error> {
        self.deserialize_seq(visitor)
    }

    fn deserialize_tuple_struct<V: Visitor<'de>>(
        self,
        _name: &'static str,
        _len: usize,
        visitor: V,
    ) -> Result<V::Value, Self::Error> {
        self.deserialize_seq(visitor)
    }

    fn deserialize_map<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        visitor.visit_map(NodeMapAccess::new(self.node, self.input, None))
    }

    fn deserialize_struct<V: Visitor<'de>>(
        self,
        _name: &'static str,
        fields: &'static [&'static str],
        visitor: V,
    ) -> Result<V::Value, Self::Error> {
        visitor.visit_map(NodeMapAccess::new(self.node, self.input, Some(fields)))
    }

    fn deserialize_enum<V: Visitor<'de>>(
        self,
        _name: &'static str,
        _variants: &'static [&'static str],
        visitor: V,
    ) -> Result<V::Value, Self::Error> {
        // If the node is a scalar string, treat it as a unit variant name.
        if self.is_scalar()
            && let KdlValue::String(s) = self.args()[0].value()
        {
            return visitor
                .visit_enum(str_deserializer(s.as_str()))
                .map_err(|err| {
                    err.with_span(
                        self.input,
                        entry_span(self.args()[0]),
                        "while deserializing this enum variant",
                    )
                });
        }

        // Otherwise, try treating the node as an externally-tagged enum:
        // if there's exactly one child node, use its name as variant, body as data.
        if let Some(children) = self.node.children() {
            let child_nodes = children.nodes();
            if child_nodes.len() == 1 {
                return visitor.visit_enum(NodeEnumAccess {
                    node: &child_nodes[0],
                    input: self.input,
                });
            }
        }

        // For nodes with properties but no children, try MAP-STYLE
        let props = self.props();
        if props.len() == 1 && self.args().is_empty() && self.node.children().is_none() {
            let prop = props[0];
            let name = prop.name().unwrap().value();
            return visitor.visit_enum(PropertyEnumAccess {
                key: name,
                entry: prop,
                input: self.input,
            });
        }

        // Fall back: just node name is variant
        visitor.visit_enum(NodeEnumAccess {
            node: self.node,
            input: self.input,
        })
    }

    fn deserialize_identifier<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        self.deserialize_str(visitor)
    }

    fn deserialize_ignored_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        visitor.visit_unit()
    }
}

impl<'a> NodeDeserializer<'a> {
    fn deserialize_scalar<'de, V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
        if self.is_scalar() {
            ValueDeserializer::new(self.args()[0], self.input).deserialize_any(visitor)
        } else {
            self.deserialize_any(visitor)
        }
    }
}

struct ArgSeqAccess<'a> {
    iter: std::vec::IntoIter<&'a KdlEntry>,
    input: &'a Arc<String>,
}

impl<'de, 'a> SeqAccess<'de> for ArgSeqAccess<'a> {
    type Error = Error;

    fn next_element_seed<T: DeserializeSeed<'de>>(
        &mut self,
        seed: T,
    ) -> Result<Option<T::Value>, Self::Error> {
        self.iter
            .next()
            .map(|e| seed.deserialize(ValueDeserializer::new(e, self.input)))
            .transpose()
    }
}

struct NodeListSeqAccess<'a> {
    iter: std::slice::Iter<'a, KdlNode>,
    input: &'a Arc<String>,
}

impl<'de, 'a> SeqAccess<'de> for NodeListSeqAccess<'a> {
    type Error = Error;

    fn next_element_seed<T: DeserializeSeed<'de>>(
        &mut self,
        seed: T,
    ) -> Result<Option<T::Value>, Self::Error> {
        self.iter
            .next()
            .map(|node| {
                seed.deserialize(NodeDeserializer {
                    node,
                    input: self.input,
                })
            })
            .transpose()
    }
}

struct NodeGroupDeserializer<'a> {
    nodes: &'a [&'a KdlNode],
    input: &'a Arc<String>,
}

impl<'de, 'a> de::Deserializer<'de> for NodeGroupDeserializer<'a> {
    type Error = Error;

    fn deserialize_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        self.deserialize_seq(visitor)
    }

    fn deserialize_seq<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        visitor.visit_seq(NodeGroupSeqAccess {
            iter: self.nodes.iter(),
            input: self.input,
        })
    }

    serde::forward_to_deserialize_any! {
        bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
        bytes byte_buf option unit unit_struct newtype_struct tuple
        tuple_struct map struct enum identifier ignored_any
    }
}

struct NodeGroupSeqAccess<'a> {
    iter: std::slice::Iter<'a, &'a KdlNode>,
    input: &'a Arc<String>,
}

impl<'de, 'a> SeqAccess<'de> for NodeGroupSeqAccess<'a> {
    type Error = Error;

    fn next_element_seed<T: DeserializeSeed<'de>>(
        &mut self,
        seed: T,
    ) -> Result<Option<T::Value>, Self::Error> {
        self.iter
            .next()
            .map(|node| {
                seed.deserialize(NodeDeserializer {
                    node,
                    input: self.input,
                })
            })
            .transpose()
    }
}

#[derive(Debug)]
struct NodeMapAccess<'a> {
    /// Properties and children combined as (key, value_source).
    entries: Vec<(Cow<'a, str>, NodeMapValue<'a>)>,
    idx: usize,
    input: &'a Arc<String>,
}

#[derive(Debug)]
enum NodeMapValue<'a> {
    Ident(&'a KdlIdentifier),
    Arg(&'a KdlEntry),
    Args(Vec<&'a KdlEntry>),
    SingleNode(&'a KdlNode),
    MultiNode(Vec<&'a KdlNode>),
    Omitted,
}

impl<'a> NodeMapAccess<'a> {
    fn new(
        node: &'a KdlNode,
        input: &'a Arc<String>,
        fields: Option<&'static [&'static str]>,
    ) -> Self {
        let mut entries: Vec<(Cow<'a, str>, NodeMapValue<'a>)> = Vec::new();

        if let Some(fields) = fields {
            if fields.contains(&"#name") {
                entries.push(("#name".into(), NodeMapValue::Ident(node.name())));
            }
            if fields.contains(&"#type")
                && let Some(ty) = node.ty()
            {
                entries.push(("#type".into(), NodeMapValue::Ident(ty)));
            }
        }
        if let Some(fields) = fields
            && let collect_all = fields.contains(&"#args")
            && let collect_rest = fields.contains(&"#rest")
        {
            let mut args = Vec::new();
            let mut rest = Vec::new();
            for (i, arg) in node
                .entries()
                .iter()
                .filter(|e| e.name().is_none())
                .enumerate()
            {
                if collect_all {
                    args.push(arg);
                }
                let idx_name = format!("#{i}");
                let ty_name = format!("{idx_name}#type");
                if let Some(ty) = arg.ty() {
                    entries.push((ty_name.into(), NodeMapValue::Ident(ty)));
                }
                if fields.contains(&idx_name.as_ref()) {
                    entries.push((idx_name.into(), NodeMapValue::Arg(arg)));
                } else if collect_rest {
                    rest.push(arg);
                }
            }
            if collect_all {
                entries.push(("#args".into(), NodeMapValue::Args(args)));
            }
            if collect_rest {
                entries.push(("#rest".into(), NodeMapValue::Args(rest)));
            }
        }

        let mut used_names = Vec::new();
        for prop in node.entries().iter().filter(|e| e.name().is_some()) {
            // SAFETY: we just filtered for things with names.
            let name = prop.name().unwrap().value();
            if let Some(fields) = fields {
                let hash_name = format!("#@{name}");
                let ty_name = format!("{hash_name}#type");
                if fields.contains(&hash_name.as_ref()) {
                    entries.push((hash_name.into(), NodeMapValue::Arg(prop)));
                }
                if let Some(ty) = prop.ty()
                    && fields.contains(&ty_name.as_ref())
                {
                    entries.push((ty_name.into(), NodeMapValue::Ident(ty)));
                }
            }
            entries.push((name.into(), NodeMapValue::Arg(prop)));
            used_names.push(name);
        }

        // Add children (grouped by node name)
        if let Some(children) = node.children() {
            let mut child_keys: Vec<&str> = Vec::new();
            let mut child_groups: std::collections::HashMap<&str, Vec<&KdlNode>> =
                std::collections::HashMap::new();
            for child in children.nodes() {
                let name = child.name().value();
                used_names.push(name);
                if !child_groups.contains_key(name) {
                    child_keys.push(name);
                }
                child_groups.entry(name).or_default().push(child);
            }
            for key in child_keys {
                let group = child_groups.remove(key).unwrap();
                if group.len() == 1 {
                    entries.push((key.into(), NodeMapValue::SingleNode(group[0])));
                } else {
                    entries.push((key.into(), NodeMapValue::MultiNode(group)));
                }
            }
        }
        if let Some(fields) = fields {
            for field in fields {
                if !field.starts_with('#') && !used_names.contains(field) {
                    entries.push((String::from(*field).into(), NodeMapValue::Omitted));
                }
            }
        }

        NodeMapAccess {
            entries,
            idx: 0,
            input,
        }
    }
}

impl<'de, 'a> MapAccess<'de> for NodeMapAccess<'a> {
    type Error = Error;

    fn next_key_seed<K: DeserializeSeed<'de>>(
        &mut self,
        seed: K,
    ) -> Result<Option<K::Value>, Self::Error> {
        if self.idx >= self.entries.len() {
            return Ok(None);
        }
        match &self.entries[self.idx].0 {
            Cow::Borrowed(s) => seed.deserialize(str_deserializer(s)),
            Cow::Owned(s) => seed.deserialize(StringDeserializer::new(s.clone())),
        }
        .map(Some)
    }

    fn next_value_seed<V: DeserializeSeed<'de>>(
        &mut self,
        seed: V,
    ) -> Result<V::Value, Self::Error> {
        let (_, ref value) = self.entries[self.idx];
        self.idx += 1;
        match value {
            NodeMapValue::Ident(ident) => {
                seed.deserialize(IdentDeserializer::new(ident, self.input))
            }
            NodeMapValue::Arg(entry) => seed.deserialize(ValueDeserializer::new(entry, self.input)),
            NodeMapValue::Args(entries) => seed.deserialize(ArgsSeqDeserializer {
                entries: entries.clone(),
                input: self.input,
            }),
            NodeMapValue::SingleNode(node) => seed.deserialize(NodeDeserializer {
                node,
                input: self.input,
            }),
            NodeMapValue::MultiNode(nodes) => seed.deserialize(NodeGroupDeserializer {
                nodes,
                input: self.input,
            }),
            NodeMapValue::Omitted => seed.deserialize(OmittedChildDeserializer),
        }
    }
}

struct ArgsSeqDeserializer<'a> {
    entries: Vec<&'a KdlEntry>,
    input: &'a Arc<String>,
}

impl<'de, 'a> Deserializer<'de> for ArgsSeqDeserializer<'a> {
    type Error = Error;

    fn deserialize_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        visitor.visit_seq(ArgSeqAccess {
            iter: self.entries.into_iter(),
            input: self.input,
        })
    }

    fn deserialize_seq<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        visitor.visit_seq(ArgSeqAccess {
            iter: self.entries.into_iter(),
            input: self.input,
        })
    }

    fn deserialize_option<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        if self.entries.is_empty() {
            visitor.visit_none()
        } else {
            visitor.visit_some(self)
        }
    }

    fn deserialize_newtype_struct<V: Visitor<'de>>(
        self,
        _: &'static str,
        visitor: V,
    ) -> Result<V::Value, Self::Error> {
        visitor.visit_newtype_struct(self)
    }

    serde::forward_to_deserialize_any! {
        bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
        bytes byte_buf unit unit_struct tuple
        tuple_struct map struct enum identifier ignored_any
    }
}

struct OmittedChildDeserializer;

impl<'de> Deserializer<'de> for OmittedChildDeserializer {
    type Error = Error;

    fn deserialize_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        visitor.visit_bool(false)
    }

    fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    where
        V: Visitor<'de>,
    {
        visitor.visit_bool(false)
    }

    fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    where
        V: Visitor<'de>,
    {
        visitor.visit_none()
    }

    serde::forward_to_deserialize_any! {
        i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
        bytes byte_buf unit unit_struct tuple newtype_struct seq
        tuple_struct map struct enum identifier ignored_any
    }
}

struct NodeEnumAccess<'a> {
    node: &'a KdlNode,
    input: &'a Arc<String>,
}

impl<'de, 'a> de::EnumAccess<'de> for NodeEnumAccess<'a> {
    type Error = Error;
    type Variant = NodeVariantAccess<'a>;

    fn variant_seed<V: DeserializeSeed<'de>>(
        self,
        seed: V,
    ) -> Result<(V::Value, Self::Variant), Self::Error> {
        let variant_name = self.node.name().value();
        let val = seed
            .deserialize(str_deserializer(variant_name))
            .map_err(|err| {
                err.with_span(
                    self.input,
                    node_span(self.node),
                    "while deserializing this enum variant",
                )
            })?;
        Ok((
            val,
            NodeVariantAccess {
                node: self.node,
                input: self.input,
            },
        ))
    }
}

struct NodeVariantAccess<'a> {
    node: &'a KdlNode,
    input: &'a Arc<String>,
}

impl<'de, 'a> de::VariantAccess<'de> for NodeVariantAccess<'a> {
    type Error = Error;

    fn unit_variant(self) -> Result<(), Self::Error> {
        Ok(())
    }

    fn newtype_variant_seed<T: DeserializeSeed<'de>>(
        self,
        seed: T,
    ) -> Result<T::Value, Self::Error> {
        seed.deserialize(NodeDeserializer {
            node: self.node,
            input: self.input,
        })
    }

    fn tuple_variant<V: Visitor<'de>>(
        self,
        _len: usize,
        visitor: V,
    ) -> Result<V::Value, Self::Error> {
        de::Deserializer::deserialize_seq(
            NodeDeserializer {
                node: self.node,
                input: self.input,
            },
            visitor,
        )
    }

    fn struct_variant<V: Visitor<'de>>(
        self,
        _fields: &'static [&'static str],
        visitor: V,
    ) -> Result<V::Value, Self::Error> {
        de::Deserializer::deserialize_map(
            NodeDeserializer {
                node: self.node,
                input: self.input,
            },
            visitor,
        )
    }
}

struct PropertyEnumAccess<'a> {
    key: &'a str,
    entry: &'a KdlEntry,
    input: &'a Arc<String>,
}

impl<'de, 'a> de::EnumAccess<'de> for PropertyEnumAccess<'a> {
    type Error = Error;
    type Variant = PropertyVariantAccess<'a>;

    fn variant_seed<V: DeserializeSeed<'de>>(
        self,
        seed: V,
    ) -> Result<(V::Value, Self::Variant), Self::Error> {
        let val = seed
            .deserialize(str_deserializer(self.key))
            .map_err(|err| {
                err.with_span(
                    self.input,
                    entry_span(self.entry),
                    "while deserializing this enum variant",
                )
            })?;
        Ok((
            val,
            PropertyVariantAccess {
                entry: self.entry,
                input: self.input,
            },
        ))
    }
}

struct PropertyVariantAccess<'a> {
    entry: &'a KdlEntry,
    input: &'a Arc<String>,
}

impl<'de, 'a> de::VariantAccess<'de> for PropertyVariantAccess<'a> {
    type Error = Error;

    fn unit_variant(self) -> Result<(), Self::Error> {
        Ok(())
    }

    fn newtype_variant_seed<T: DeserializeSeed<'de>>(
        self,
        seed: T,
    ) -> Result<T::Value, Self::Error> {
        seed.deserialize(ValueDeserializer::new(self.entry, self.input))
    }

    fn tuple_variant<V: Visitor<'de>>(
        self,
        _len: usize,
        _visitor: V,
    ) -> Result<V::Value, Self::Error> {
        Err(Error::new(
            "tuple variants not supported from KDL properties",
        ))
        .map_err(|err| {
            err.with_span(
                self.input,
                entry_span(self.entry),
                "while deserializing this KDL property",
            )
        })
    }

    fn struct_variant<V: Visitor<'de>>(
        self,
        _fields: &'static [&'static str],
        _visitor: V,
    ) -> Result<V::Value, Self::Error> {
        Err(Error::new(
            "struct variants not supported from KDL properties",
        ))
        .map_err(|err| {
            err.with_span(
                self.input,
                entry_span(self.entry),
                "while deserializing this KDL property",
            )
        })
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[cfg(feature = "span")]
    use miette::SourceCode;
    use serde::Deserialize;

    #[test]
    fn simple_struct() {
        #[derive(Deserialize, Debug, PartialEq)]
        struct Config {
            name: String,
            port: u16,
        }

        let kdl = r#"
name "my-app"
port 8080
"#;
        let config: Config = from_str(kdl).unwrap();
        assert_eq!(
            config,
            Config {
                name: "my-app".into(),
                port: 8080,
            }
        );
    }

    #[test]
    fn nested_struct() {
        #[derive(Deserialize, Debug, PartialEq)]
        struct Config {
            server: Server,
        }

        #[derive(Deserialize, Debug, PartialEq)]
        struct Server {
            host: String,
            port: u16,
        }

        let kdl = r#"
server {
    host "localhost"
    port 8080
}
"#;
        let config: Config = from_str(kdl).unwrap();
        assert_eq!(
            config,
            Config {
                server: Server {
                    host: "localhost".into(),
                    port: 8080,
                },
            }
        );
    }

    #[test]
    fn node_with_properties() {
        #[derive(Deserialize, Debug, PartialEq)]
        struct Config {
            server: Server,
        }

        #[derive(Deserialize, Debug, PartialEq)]
        struct Server {
            host: String,
            port: u16,
        }

        let kdl = r#"server host="localhost" port=8080"#;
        let config: Config = from_str(kdl).unwrap();
        assert_eq!(
            config,
            Config {
                server: Server {
                    host: "localhost".into(),
                    port: 8080,
                },
            }
        );
    }

    #[test]
    fn sequence_of_args() {
        #[derive(Deserialize, Debug, PartialEq)]
        struct Config {
            values: Vec<i32>,
        }

        let kdl = r#"values 1 2 3"#;
        let config: Config = from_str(kdl).unwrap();
        assert_eq!(
            config,
            Config {
                values: vec![1, 2, 3]
            }
        );
    }

    #[test]
    fn repeated_nodes_as_seq() {
        #[derive(Deserialize, Debug, PartialEq)]
        struct Config {
            route: Vec<String>,
        }

        let kdl = r#"
route "/api/users"
route "/api/posts"
route "/api/comments"
"#;
        let config: Config = from_str(kdl).unwrap();
        assert_eq!(
            config,
            Config {
                route: vec![
                    "/api/users".into(),
                    "/api/posts".into(),
                    "/api/comments".into(),
                ],
            }
        );
    }

    #[test]
    fn boolean_and_null() {
        #[derive(Deserialize, Debug, PartialEq)]
        struct Config {
            enabled: bool,
            disabled: bool,
            nothing: Option<String>,
        }

        let kdl = r#"
enabled #true
disabled #false
nothing #null
"#;
        let config: Config = from_str(kdl).unwrap();
        assert_eq!(
            config,
            Config {
                enabled: true,
                disabled: false,
                nothing: None,
            }
        );
    }

    #[test]
    fn option_some() {
        #[derive(Deserialize, Debug, PartialEq)]
        struct Config {
            name: Option<String>,
        }

        let kdl = r#"name "hello""#;
        let config: Config = from_str(kdl).unwrap();
        assert_eq!(
            config,
            Config {
                name: Some("hello".into()),
            }
        );
    }

    #[test]
    fn float_values() {
        #[derive(Deserialize, Debug, PartialEq)]
        struct Config {
            ratio: f64,
        }

        let kdl = r#"ratio 3.14"#;
        let config: Config = from_str(kdl).unwrap();
        assert!((config.ratio - 3.14).abs() < f64::EPSILON);
    }

    #[test]
    fn enum_unit_variant() {
        #[derive(Deserialize, Debug, PartialEq)]
        enum Color {
            Red,
            Green,
            Blue,
        }

        #[derive(Deserialize, Debug, PartialEq)]
        struct Config {
            color: Color,
        }

        let kdl = r#"color "Red""#;
        let config: Config = from_str(kdl).unwrap();
        assert_eq!(config, Config { color: Color::Red });
    }

    #[test]
    fn deeply_nested() {
        #[derive(Deserialize, Debug, PartialEq)]
        struct Root {
            level1: Level1,
        }

        #[derive(Deserialize, Debug, PartialEq)]
        struct Level1 {
            level2: Level2,
        }

        #[derive(Deserialize, Debug, PartialEq)]
        struct Level2 {
            value: i32,
        }

        let kdl = r#"
level1 {
    level2 {
        value 42
    }
}
"#;
        let root: Root = from_str(kdl).unwrap();
        assert_eq!(
            root,
            Root {
                level1: Level1 {
                    level2: Level2 { value: 42 },
                },
            }
        );
    }

    #[test]
    fn children_as_seq() {
        #[derive(Deserialize, Debug, PartialEq)]
        struct Item {
            name: String,
        }

        let kdl = r#"
items {
    item {
        name "a"
    }
    item {
        name "b"
    }
}
"#;

        #[derive(Deserialize, Debug, PartialEq)]
        struct Config {
            items: Items,
        }

        #[derive(Deserialize, Debug, PartialEq)]
        struct Items {
            item: Vec<Item>,
        }

        let config: Config = from_str(kdl).unwrap();
        assert_eq!(
            config,
            Config {
                items: Items {
                    item: vec![Item { name: "a".into() }, Item { name: "b".into() },],
                },
            }
        );
    }

    #[test]
    fn mixed_props_and_children() {
        #[derive(Deserialize, Debug, PartialEq)]
        struct Server {
            host: String,
            port: u16,
            routes: Routes,
        }

        #[derive(Deserialize, Debug, PartialEq)]
        struct Routes {
            path: Vec<String>,
        }

        #[derive(Deserialize, Debug, PartialEq)]
        struct Config {
            server: Server,
        }

        let kdl = r#"
server host="localhost" port=8080 {
    routes {
        path "/a"
        path "/b"
    }
}
"#;
        let config: Config = from_str(kdl).unwrap();
        assert_eq!(
            config,
            Config {
                server: Server {
                    host: "localhost".into(),
                    port: 8080,
                    routes: Routes {
                        path: vec!["/a".into(), "/b".into()],
                    },
                },
            }
        );
    }

    #[test]
    fn empty_document() {
        #[derive(Deserialize, Debug, PartialEq)]
        struct Config {}

        let config: Config = from_str("").unwrap();
        assert_eq!(config, Config {});
    }

    #[test]
    fn hashmap() {
        use std::collections::HashMap;

        let kdl = r#"
alpha 1
beta 2
gamma 3
"#;
        let map: HashMap<String, i32> = from_str(kdl).unwrap();
        assert_eq!(map.get("alpha"), Some(&1));
        assert_eq!(map.get("beta"), Some(&2));
        assert_eq!(map.get("gamma"), Some(&3));
    }

    #[test]
    fn newtype_struct() {
        #[derive(Deserialize, Debug, PartialEq)]
        struct Port(u16);

        #[derive(Deserialize, Debug, PartialEq)]
        struct Config {
            port: Port,
        }

        let kdl = r#"port 8080"#;
        let config: Config = from_str(kdl).unwrap();
        assert_eq!(config, Config { port: Port(8080) });
    }

    #[test]
    fn integer_types() {
        #[derive(Deserialize, Debug, PartialEq)]
        struct Config {
            a: i8,
            b: i16,
            c: i32,
            d: i64,
            e: u8,
            f: u16,
            g: u32,
            h: u64,
        }

        let kdl = r#"
a 1
b 2
c 3
d 4
e 5
f 6
g 7
h 8
"#;
        let config: Config = from_str(kdl).unwrap();
        assert_eq!(
            config,
            Config {
                a: 1,
                b: 2,
                c: 3,
                d: 4,
                e: 5,
                f: 6,
                g: 7,
                h: 8,
            }
        );
    }

    #[test]
    fn rename_props() {
        #[derive(Deserialize, Debug, PartialEq)]
        struct Server {
            #[serde(rename = "#@host")]
            host: String,
            #[serde(rename = "#@port")]
            port: u16,
        }

        #[derive(Deserialize, Debug, PartialEq)]
        struct Config {
            server: Server,
        }

        let kdl = "server host=localhost port=8080";
        let config: Config = from_str(kdl).unwrap();
        assert_eq!(
            config,
            Config {
                server: Server {
                    host: "localhost".into(),
                    port: 8080,
                },
            }
        );
    }

    #[test]
    fn rename_args() {
        #[derive(Deserialize, Debug, PartialEq)]
        #[serde(rename_all = "kebab-case")]
        enum HostType {
            IpAddr,
            Hostname,
        }

        #[derive(Deserialize, Debug, PartialEq)]
        struct Server {
            #[serde(rename = "#type")]
            server_type: String,
            #[serde(rename = "#0#type")]
            host_type: HostType,
            #[serde(rename = "#0")]
            host: String,
            #[serde(rename = "#@port#type")]
            port_type: String,
            #[serde(rename = "#@port")]
            port: u16,
            #[serde(rename = "#args")]
            all: Vec<String>,
        }

        #[derive(Deserialize, Debug, PartialEq)]
        struct Config {
            server: Server,
        }

        let kdl = "(linux-debian-arm64)server (hostname)localhost port=(number)8080 remote";
        let config: Config = from_str(kdl).unwrap();
        assert_eq!(
            config,
            Config {
                server: Server {
                    server_type: "linux-debian-arm64".into(),
                    host_type: HostType::Hostname,
                    host: "localhost".into(),
                    port_type: "number".into(),
                    port: 8080,
                    all: Vec::from(["localhost".into(), "remote".into()])
                },
            }
        );
    }

    #[test]
    fn rename_all_args() {
        #[derive(Deserialize, Debug, PartialEq)]
        struct Command {
            #[serde(rename = "#@name")]
            name: String,
            #[serde(rename = "#args")]
            args: Vec<String>,
        }

        #[derive(Deserialize, Debug, PartialEq)]
        struct Config {
            command: Command,
        }

        let kdl = "command name=run --verbose --output result.txt";
        let config: Config = from_str(kdl).unwrap();
        assert_eq!(
            config,
            Config {
                command: Command {
                    name: "run".into(),
                    args: vec!["--verbose".into(), "--output".into(), "result.txt".into(),],
                },
            }
        );
    }

    #[test]
    fn rename_rest_args() {
        #[derive(Deserialize, Debug, PartialEq)]
        struct Command {
            #[serde(rename = "#0")]
            name: String,
            #[serde(rename = "#rest")]
            args: Vec<String>,
        }

        #[derive(Deserialize, Debug, PartialEq)]
        struct Config {
            command: Command,
        }

        let kdl = "command run --verbose --output result.txt";
        let config: Config = from_str(kdl).unwrap();
        assert_eq!(
            config,
            Config {
                command: Command {
                    name: "run".into(),
                    args: vec!["--verbose".into(), "--output".into(), "result.txt".into(),],
                },
            }
        );
    }

    #[test]
    fn rename_children_args() {
        #[derive(Deserialize, Debug, PartialEq)]
        struct Server {
            #[serde(rename = "#@host")]
            host: String,
            #[serde(rename = "#args")]
            ports: Vec<u16>,
        }

        #[derive(Deserialize, Debug, PartialEq)]
        struct Config {
            server: Server,
        }

        let kdl = "server host=localhost 8080 8081 8082";
        let config: Config = from_str(kdl).unwrap();
        assert_eq!(
            config,
            Config {
                server: Server {
                    host: "localhost".into(),
                    ports: vec![8080, 8081, 8082],
                },
            }
        );
    }

    #[test]
    fn bool_flag_children() {
        #[derive(Deserialize, Debug, PartialEq)]
        #[serde(rename_all = "kebab-case")]
        struct Server {
            host: String,
            active: bool,
        }

        #[derive(Deserialize, Debug, PartialEq)]
        struct Config {
            server: Server,
        }

        let kdl = "server host=localhost { active }";
        let config: Config = from_str(kdl).unwrap();
        assert_eq!(
            config,
            Config {
                server: Server {
                    host: "localhost".into(),
                    active: true,
                },
            }
        );

        let kdl = "server host=localhost active=#true";
        let config: Config = from_str(kdl).unwrap();
        assert_eq!(
            config,
            Config {
                server: Server {
                    host: "localhost".into(),
                    active: true,
                },
            }
        );

        let kdl = "server host=localhost";
        let config: Config = from_str(kdl).unwrap();
        assert_eq!(
            config,
            Config {
                server: Server {
                    host: "localhost".into(),
                    active: false,
                },
            }
        );

        let kdl = "server host=localhost { }";
        let config: Config = from_str(kdl).unwrap();
        assert_eq!(
            config,
            Config {
                server: Server {
                    host: "localhost".into(),
                    active: false,
                },
            }
        );
    }

    // TODO(@zkat): Can't figure out how to do internally tagged stuff just yet...
    // #[test]
    // fn internal_tag_rename() {
    //     #[derive(Deserialize, Debug, PartialEq)]
    //     #[serde(tag = "#0", rename_all = "kebab-case")]
    //     enum Upstream {
    //         Git {
    //             #[serde(rename = "#1")]
    //             url: String,
    //             hash: Option<String>,
    //         },
    //         Svn {
    //             #[serde(rename = "#1")]
    //             url: String,
    //             rev: Option<String>,
    //         },
    //     }

    //     #[derive(Deserialize, Debug, PartialEq)]
    //     struct Config {
    //         #[serde(rename = "upstream")]
    //         upstreams: Vec<Upstream>,
    //     }

    //     let kdl = r#"upstream git "https://codeberg.org/kdl/kdl-rs""#;
    //     let config: Config = from_str(kdl).unwrap();
    //     assert_eq!(
    //         config,
    //         Config {
    //             upstreams: vec![Upstream::Git {
    //                 url: "https://codeberg.org/kdl/kdl-rs".into(),
    //                 hash: None,
    //             }]
    //         }
    //     );
    // }

    #[test]
    fn error_span_and_diagnostic() {
        #[derive(Deserialize, Debug, PartialEq)]
        struct Config {
            port: u16,
        }

        let kdl = "port nope";
        let err = from_str::<Config>(kdl).unwrap_err();

        let labels: Vec<_> = err.labels().unwrap().collect();
        assert_eq!(
            labels[0].label().unwrap(),
            "while deserializing this KDL value"
        );
        let diagnostic = err.diagnostic().unwrap();
        let diag_labels: Vec<_> = diagnostic.labels().unwrap().collect();
        assert_eq!(
            diag_labels[0].label().unwrap(),
            "while deserializing this KDL value"
        );

        #[cfg(feature = "span")]
        {
            let span = err.span().unwrap();
            assert_eq!(span, diagnostic.span);
            assert_eq!(kdl.read_span(&span, 0, 0).unwrap().data(), b"nope",);

            assert_eq!(
                diagnostic
                    .source_code()
                    .unwrap()
                    .read_span(labels[0].inner(), 0, 0)
                    .unwrap()
                    .data(),
                b"nope",
            );
        }
    }
}
