use serde::{Serialize, Deserialize};
use std::fmt;

#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum LeaderType {
    Straight,
    Spline,
}

impl Default for LeaderType {
    fn default() -> Self {
        LeaderType::Straight
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum LeaderAttachmentType {
    AttachmentTop,
    AttachmentMiddle,
    AttachmentBottom,
}

impl Default for LeaderAttachmentType {
    fn default() -> Self {
        LeaderAttachmentType::AttachmentTop
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum LeaderBranchType {
    Left,
    Right,
}

impl Default for LeaderBranchType {
    fn default() -> Self {
        LeaderBranchType::Left
    }
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct LeaderLine {
    pub points: Vec<crate::geometry::Point>,
    pub leader_type: LeaderType,
    pub branch_type: LeaderBranchType,
    pub last_segment_angle: f64,
}

impl Default for LeaderLine {
    fn default() -> Self {
        Self::new()
    }
}

impl LeaderLine {
    #[inline]
    pub fn new() -> Self {
        Self {
            points: Vec::new(),
            leader_type: LeaderType::Straight,
            branch_type: LeaderBranchType::Left,
            last_segment_angle: 0.0,
        }
    }

    #[inline]
    pub fn with_points(points: &[crate::geometry::Point]) -> Self {
        let last_segment_angle = if points.len() >= 2 {
            let dx = points[points.len() - 1].x - points[points.len() - 2].x;
            let dy = points[points.len() - 1].y - points[points.len() - 2].y;
            dy.atan2(dx)
        } else {
            0.0
        };

        Self {
            points: points.to_vec(),
            leader_type: LeaderType::Straight,
            branch_type: LeaderBranchType::Left,
            last_segment_angle,
        }
    }

    #[inline]
    pub fn add_point(&mut self, point: crate::geometry::Point) {
        if self.points.len() >= 2 {
            let last_idx = self.points.len() - 1;
            let dx = point.x - self.points[last_idx].x;
            let dy = point.y - self.points[last_idx].y;
            self.last_segment_angle = dy.atan2(dx);
        }
        self.points.push(point);
    }

    #[inline]
    pub fn point_count(&self) -> usize {
        self.points.len()
    }

    #[inline]
    pub fn is_empty(&self) -> bool {
        self.points.is_empty()
    }

    #[inline]
    pub fn length(&self) -> f64 {
        if self.points.len() < 2 {
            return 0.0;
        }
        let mut total = 0.0;
        for i in 1..self.points.len() {
            total += self.points[i].distance_to(&self.points[i - 1]);
        }
        total
    }

    #[inline]
    pub fn start_point(&self) -> Option<&crate::geometry::Point> {
        self.points.first()
    }

    #[inline]
    pub fn end_point(&self) -> Option<&crate::geometry::Point> {
        self.points.last()
    }
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Arrowhead {
    pub position: crate::geometry::Point,
    pub size: f64,
    pub arrowhead_type: ArrowheadType,
    pub angle: f64,
}

impl Default for Arrowhead {
    fn default() -> Self {
        Self::new()
    }
}

impl Arrowhead {
    #[inline]
    pub fn new() -> Self {
        Self {
            position: crate::geometry::Point::origin(),
            size: 2.5,
            arrowhead_type: ArrowheadType::ClosedFilled,
            angle: 0.0,
        }
    }

    #[inline]
    pub fn with_position(mut self, position: crate::geometry::Point) -> Self {
        self.position = position;
        self
    }

    #[inline]
    pub fn with_size(mut self, size: f64) -> Self {
        self.size = size;
        self
    }

    #[inline]
    pub fn with_type(mut self, arrow_type: ArrowheadType) -> Self {
        self.arrowhead_type = arrow_type;
        self
    }

    #[inline]
    pub fn set_angle(&mut self, angle: f64) {
        self.angle = angle;
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum ArrowheadType {
    None,
    DotSmall,
    Dot,
    ArrowOpen,
    ArrowOpen90,
    ArrowOpen45,
    ArrowClosed,
    ArrowClosedFilled,
    Tick,
    Tick2x,
    Triangle,
    Triangle90,
    Triangle45,
    Square,
    Hexagon,
    Circle,
    CircleFilled,
    DotBlank,
    Origin,
    Origin2,
    NoneFilled,
    User,
}

impl Default for ArrowheadType {
    fn default() -> Self {
        ArrowheadType::ArrowClosedFilled
    }
}

impl ArrowheadType {
    #[inline]
    pub fn name(&self) -> &str {
        match self {
            ArrowheadType::None => "None",
            ArrowheadType::DotSmall => "Dot Small",
            ArrowheadType::Dot => "Dot",
            ArrowheadType::ArrowOpen => "Open",
            ArrowheadType::ArrowOpen90 => "Open 90",
            ArrowheadType::ArrowOpen45 => "Open 45",
            ArrowheadType::ArrowClosed => "Closed",
            ArrowheadType::ArrowClosedFilled => "Closed Filled",
            ArrowheadType::Tick => "Tick",
            ArrowheadType::Tick2x => "Tick 2x",
            ArrowheadType::Triangle => "Triangle",
            ArrowheadType::Triangle90 => "Triangle 90",
            ArrowheadType::Triangle45 => "Triangle 45",
            ArrowheadType::Square => "Square",
            ArrowheadType::Hexagon => "Hexagon",
            ArrowheadType::Circle => "Circle",
            ArrowheadType::CircleFilled => "Circle Filled",
            ArrowheadType::DotBlank => "Dot Blank",
            ArrowheadType::Origin => "Origin",
            ArrowheadType::Origin2 => "Origin 2",
            ArrowheadType::NoneFilled => "None Filled",
            ArrowheadType::User => "User Defined",
        }
    }
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct MTextContent {
    pub text: String,
    pub width: f64,
    pub text_style: crate::text::TextStyle,
    pub alignment: crate::text::TextAlignment,
    pub line_spacing: f64,
}

impl Default for MTextContent {
    fn default() -> Self {
        Self {
            text: String::new(),
            width: 0.0,
            text_style: crate::text::TextStyle::default(),
            alignment: crate::text::TextAlignment::Left,
            line_spacing: 1.0,
        }
    }
}

impl MTextContent {
    #[inline]
    pub fn new(text: &str) -> Self {
        Self {
            text: text.to_string(),
            ..Default::default()
        }
    }

    #[inline]
    pub fn with_width(mut self, width: f64) -> Self {
        self.width = width;
        self
    }

    #[inline]
    pub fn set_text(&mut self, text: &str) {
        self.text = text.to_string();
    }

    #[inline]
    pub fn append_text(&mut self, text: &str) {
        self.text.push_str(text);
    }

    #[inline]
    pub fn is_empty(&self) -> bool {
        self.text.is_empty()
    }
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct BlockContent {
    pub block_name: String,
    pub position: crate::geometry::Point,
    pub scale: (f64, f64),
    pub rotation: f64,
    pub attribute_values: Vec<(String, String)>,
}

impl Default for BlockContent {
    fn default() -> Self {
        Self::new()
    }
}

impl BlockContent {
    #[inline]
    pub fn new() -> Self {
        Self {
            block_name: String::new(),
            position: crate::geometry::Point::origin(),
            scale: (1.0, 1.0),
            rotation: 0.0,
            attribute_values: Vec::new(),
        }
    }

    #[inline]
    pub fn with_block(mut self, block_name: &str) -> Self {
        self.block_name = block_name.to_string();
        self
    }

    #[inline]
    pub fn set_attribute(&mut self, tag: &str, value: &str) {
        if let Some((_, val)) = self.attribute_values.iter_mut().find(|(t, _)| t == tag) {
            *val = value.to_string();
        } else {
            self.attribute_values.push((tag.to_string(), value.to_string()));
        }
    }

    #[inline]
    pub fn get_attribute(&self, tag: &str) -> Option<&str> {
        self.attribute_values.iter()
            .find(|(t, _)| t == tag)
            .map(|(_, v)| v.as_str())
    }
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum MultileaderContent {
    MText(MTextContent),
    Block(BlockContent),
}

impl Default for MultileaderContent {
    fn default() -> Self {
        MultileaderContent::MText(MTextContent::default())
    }
}

impl MultileaderContent {
    #[inline]
    pub fn mtext(text: &str) -> Self {
        MultileaderContent::MText(MTextContent::new(text))
    }

    #[inline]
    pub fn block(block_name: &str) -> Self {
        MultileaderContent::Block(BlockContent::with_block(block_name))
    }

    #[inline]
    pub fn is_mtext(&self) -> bool {
        matches!(self, MultileaderContent::MText(_))
    }

    #[inline]
    pub fn is_block(&self) -> bool {
        matches!(self, MultileaderContent::Block(_))
    }
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Multileader {
    pub object_id: super::data_structure::ObjectId,
    pub style_name: String,
    pub leaders: Vec<LeaderLine>,
    pub arrowheads: Vec<Arrowhead>,
    pub content: MultileaderContent,
    pub content_attachment: LeaderAttachmentType,
    pub last_leader_point: crate::geometry::Point,
    pub dogleg_vector: crate::geometry::Point,
    pub dogleg_length: f64,
    pub branch_angle: f64,
    pub is_landing_set: bool,
    pub landing_gap: f64,
    pub enable_frame_text: bool,
    pub text_height: f64,
    pub text_rotation: f64,
}

impl Default for Multileader {
    fn default() -> Self {
        Self::new()
    }
}

impl Multileader {
    #[inline]
    pub fn new() -> Self {
        Self {
            object_id: super::data_structure::ObjectId::new(),
            style_name: "Standard".to_string(),
            leaders: Vec::new(),
            arrowheads: Vec::new(),
            content: MultileaderContent::MText(MTextContent::new("")),
            content_attachment: LeaderAttachmentType::AttachmentTop,
            last_leader_point: crate::geometry::Point::origin(),
            dogleg_vector: crate::geometry::Point::new(1.0, 0.0, 0.0),
            dogleg_length: 8.0,
            branch_angle: 90.0_f64.to_radians(),
            is_landing_set: true,
            landing_gap: 2.0,
            enable_frame_text: false,
            text_height: 2.5,
            text_rotation: 0.0,
        }
    }

    #[inline]
    pub fn with_content(mut self, content: MultileaderContent) -> Self {
        self.content = content;
        self
    }

    #[inline]
    pub fn add_leader(&mut self, leader: LeaderLine) {
        self.leaders.push(leader);
    }

    #[inline]
    pub fn add_leader_with_arrowhead(&mut self, leader: LeaderLine, arrowhead: Arrowhead) {
        self.leaders.push(leader.clone());
        self.arrowheads.push(arrowhead);
    }

    #[inline]
    pub fn leader_count(&self) -> usize {
        self.leaders.len()
    }

    #[inline]
    pub fn is_empty(&self) -> bool {
        self.leaders.is_empty()
    }

    #[inline]
    pub fn set_style(&mut self, style_name: &str) {
        self.style_name = style_name.to_string();
    }

    #[inline]
    pub fn set_text(&mut self, text: &str) {
        if let MultileaderContent::MText(mtext) = &mut self.content {
            mtext.set_text(text);
        }
    }

    #[inline]
    pub fn get_text(&self) -> Option<&str> {
        match &self.content {
            MultileaderContent::MText(mtext) => Some(&mtext.text),
            _ => None,
        }
    }

    #[inline]
    pub fn set_dogleg_length(&mut self, length: f64) {
        self.dogleg_length = length;
    }

    #[inline]
    pub fn set_branch_angle(&mut self, angle: f64) {
        self.branch_angle = angle;
    }

    #[inline]
    pub fn set_content_attachment(&mut self, attachment: LeaderAttachmentType) {
        self.content_attachment = attachment;
    }

    #[inline]
    pub fn rebuild_leaders(&mut self) {
        for (idx, leader) in self.leaders.iter_mut().enumerate() {
            if let Some(end_point) = leader.points.last() {
                let dx = end_point.x - self.last_leader_point.x;
                let dy = end_point.y - self.last_leader_point.y;
                let base_angle = dy.atan2(dx);

                let dogleg_angle = base_angle + self.branch_angle / 2.0;

                let new_point = crate::geometry::Point::new(
                    end_point.x + dogleg_angle.cos() * self.dogleg_length,
                    end_point.y + dogleg_angle.sin() * self.dogleg_length,
                    end_point.z,
                );

                if idx == 0 {
                    leader.points.insert(leader.points.len() - 1, new_point);
                } else {
                    leader.points.insert(1, new_point);
                }
            }
        }
    }
}

impl fmt::Display for Multileader {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "MLEADER: {} leaders, {} arrowheads", self.leaders.len(), self.arrowheads.len())
    }
}

#[derive(Debug, Clone)]
pub struct MultileaderBuilder {
    multileader: Multileader,
}

impl Default for MultileaderBuilder {
    fn default() -> Self {
        Self::new()
    }
}

impl MultileaderBuilder {
    #[inline]
    pub fn new() -> Self {
        Self {
            multileader: Multileader::new(),
        }
    }

    #[inline]
    pub fn style(mut self, style_name: &str) -> Self {
        self.multileader.set_style(style_name);
        self
    }

    #[inline]
    pub fn content(mut self, content: MultileaderContent) -> Self {
        self.multileader.content = content;
        self
    }

    #[inline]
    pub fn text(mut self, text: &str) -> Self {
        self.multileader.set_text(text);
        self
    }

    #[inline]
    pub fn add_leader_point(&mut self, point: crate::geometry::Point) {
        if let Some(last_leader) = self.multileader.leaders.last_mut() {
            last_leader.add_point(point);
        } else {
            let mut leader = LeaderLine::new();
            leader.add_point(point);
            self.multileader.leaders.push(leader);
        }
        self.multileader.last_leader_point = point;
    }

    #[inline]
    pub fn start_leader(&mut self, point: crate::geometry::Point) {
        let leader = LeaderLine::new();
        self.multileader.leaders.push(leader);
        self.multileader.last_leader_point = point;
    }

    #[inline]
    pub fn add_arrowhead(&mut self, arrowhead: Arrowhead) {
        self.multileader.arrowheads.push(arrowhead);
    }

    #[inline]
    pub fn set_dogleg_length(mut self, length: f64) -> Self {
        self.multileader.set_dogleg_length(length);
        self
    }

    #[inline]
    pub fn set_branch_angle(mut self, angle: f64) -> Self {
        self.multileader.set_branch_angle(angle);
        self
    }

    #[inline]
    pub fn set_content_attachment(mut self, attachment: LeaderAttachmentType) -> Self {
        self.multileader.set_content_attachment(attachment);
        self
    }

    #[inline]
    pub fn build(self) -> Multileader {
        self.multileader
    }

    #[inline]
    pub fn build_mut(&mut self) -> &mut Multileader {
        &mut self.multileader
    }
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct MultileaderStyle {
    pub name: String,
    pub description: String,
    pub arrowhead_type: ArrowheadType,
    pub arrowhead_size: f64,
    pub leader_type: LeaderType,
    pub content_type: ContentType,
    pub text_style: crate::text::TextStyle,
    pub text_height: f64,
    pub text_rotation: f64,
    pub text_alignment: crate::text::TextAlignment,
    pub text_attachment: TextAttachment,
    pub text_frame_enabled: bool,
    pub landing_gap: f64,
    pub dogleg_length: f64,
    pub branch_angle: f64,
    pub enable_frame_text: bool,
    pub scale_factor: f64,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum ContentType {
    MText,
    Block,
    CopyContent,
}

impl Default for ContentType {
    fn default() -> Self {
        ContentType::MText
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum TextAttachment {
    TopOfTop,
    MiddleOfTop,
    Middle,
    BottomOfTop,
    BottomOfBottom,
    MiddleOfBottom,
    AttachmentBottom,
}

impl Default for TextAttachment {
    fn default() -> Self {
        TextAttachment::TopOfTop
    }
}

impl Default for MultileaderStyle {
    fn default() -> Self {
        Self::new("Standard")
    }
}

impl MultileaderStyle {
    #[inline]
    pub fn new(name: &str) -> Self {
        Self {
            name: name.to_string(),
            description: String::new(),
            arrowhead_type: ArrowheadType::ArrowClosedFilled,
            arrowhead_size: 2.5,
            leader_type: LeaderType::Straight,
            content_type: ContentType::MText,
            text_style: crate::text::TextStyle::default(),
            text_height: 2.5,
            text_rotation: 0.0,
            text_alignment: crate::text::TextAlignment::Left,
            text_attachment: TextAttachment::TopOfTop,
            text_frame_enabled: false,
            landing_gap: 2.0,
            dogleg_length: 8.0,
            branch_angle: 90.0_f64.to_radians(),
            enable_frame_text: false,
            scale_factor: 1.0,
        }
    }

    #[inline]
    pub fn set_arrowhead_type(&mut self, arrow_type: ArrowheadType) {
        self.arrowhead_type = arrow_type;
    }

    #[inline]
    pub fn set_arrowhead_size(&mut self, size: f64) {
        self.arrowhead_size = size;
    }

    #[inline]
    pub fn set_text_height(&mut self, height: f64) {
        self.text_height = height;
    }

    #[inline]
    pub fn set_dogleg_length(&mut self, length: f64) {
        self.dogleg_length = length;
    }

    #[inline]
    pub fn set_branch_angle(&mut self, angle: f64) {
        self.branch_angle = angle;
    }

    #[inline]
    pub fn create_multileader(&self) -> Multileader {
        Multileader::new()
            .with_content(MultileaderContent::MText(MTextContent::new("")))
    }
}

#[derive(Debug, Clone)]
pub struct MultileaderManager {
    multileaders: std::collections::HashMap<super::data_structure::ObjectId, Multileader>,
    styles: std::collections::HashMap<String, MultileaderStyle>,
    current_style: String,
    active_multileader: Option<super::data_structure::ObjectId>,
}

impl Default for MultileaderManager {
    fn default() -> Self {
        Self::new()
    }
}

impl MultileaderManager {
    #[inline]
    pub fn new() -> Self {
        let mut manager = Self {
            multileaders: std::collections::HashMap::new(),
            styles: std::collections::HashMap::new(),
            current_style: "Standard".to_string(),
            active_multileader: None,
        };
        manager.register_builtin_styles();
        manager
    }

    fn register_builtin_styles(&mut self) {
        self.styles.insert("Standard".to_string(), MultileaderStyle::new("Standard"));
        self.styles.insert("StandardWithFrame".to_string(), {
            let mut style = MultileaderStyle::new("StandardWithFrame");
            style.text_frame_enabled = true;
            style
        });
    }

    #[inline]
    pub fn add(&mut self, multileader: Multileader) -> super::data_structure::ObjectId {
        let object_id = multileader.object_id;
        self.multileaders.insert(object_id, multileader);
        object_id
    }

    #[inline]
    pub fn create(&mut self) -> super::data_structure::ObjectId {
        let style = self.styles.get(&self.current_style).cloned().unwrap_or_default();
        let multileader = style.create_multileader();
        self.add(multileader)
    }

    #[inline]
    pub fn get(&self, object_id: &super::data_structure::ObjectId) -> Option<&Multileader> {
        self.multileaders.get(object_id)
    }

    #[inline]
    pub fn get_mut(&mut self, object_id: &super::data_structure::ObjectId) -> Option<&mut Multileader> {
        self.multileaders.get_mut(object_id)
    }

    #[inline]
    pub fn remove(&mut self, object_id: &super::data_structure::ObjectId) -> bool {
        self.multileaders.remove(object_id).is_some()
    }

    #[inline]
    pub fn count(&self) -> usize {
        self.multileaders.len()
    }

    #[inline]
    pub fn clear(&mut self) {
        self.multileaders.clear();
    }

    #[inline]
    pub fn set_style(&mut self, style_name: &str) -> bool {
        if self.styles.contains_key(style_name) {
            self.current_style = style_name.to_string();
            true
        } else {
            false
        }
    }

    #[inline]
    pub fn current_style(&self) -> &str {
        &self.current_style
    }

    #[inline]
    pub fn add_style(&mut self, style: MultileaderStyle) -> bool {
        if style.name.is_empty() {
            return false;
        }
        self.styles.insert(style.name.clone(), style);
        true
    }

    #[inline]
    pub fn get_style(&self, name: &str) -> Option<&MultileaderStyle> {
        self.styles.get(name)
    }

    #[inline]
    pub fn style_names(&self) -> Vec<&str> {
        self.styles.keys().map(|s| s.as_str()).collect()
    }

    #[inline]
    pub fn set_active(&mut self, object_id: Option<super::data_structure::ObjectId>) {
        self.active_multileader = object_id;
    }

    #[inline]
    pub fn active(&self) -> Option<&Multileader> {
        self.active_multileader.as_ref().and_then(|id| self.get(id))
    }

    #[inline]
    pub fn active_mut(&mut self) -> Option<&mut Multileader> {
        self.active_multileader.as_ref().and_then(|id| self.get_mut(id))
    }

    #[inline]
    pub fn add_leader_to_active(&mut self, point: crate::geometry::Point) -> bool {
        if let Some(mleader) = self.active_mut() {
            if let Some(last_leader) = mleader.leaders.last_mut() {
                last_leader.add_point(point);
            } else {
                let mut leader = LeaderLine::new();
                leader.add_point(point);
                mleader.leaders.push(leader);
            }
            mleader.last_leader_point = point;
            true
        } else {
            false
        }
    }

    #[inline]
    pub fn add_leader_point(&mut self, object_id: &super::data_structure::ObjectId, point: crate::geometry::Point) -> bool {
        if let Some(mleader) = self.get_mut(object_id) {
            if let Some(last_leader) = mleader.leaders.last_mut() {
                last_leader.add_point(point);
            } else {
                let mut leader = LeaderLine::new();
                leader.add_point(point);
                mleader.leaders.push(leader);
            }
            mleader.last_leader_point = point;
            true
        } else {
            false
        }
    }

    #[inline]
    pub fn all(&self) -> &std::collections::HashMap<super::data_structure::ObjectId, Multileader> {
        &self.multileaders
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_leader_line() {
        let leader = LeaderLine::new();
        assert!(leader.is_empty());

        let points = vec![
            Point::new(0.0, 0.0, 0.0),
            Point::new(10.0, 0.0, 0.0),
            Point::new(10.0, 10.0, 0.0),
        ];
        let leader = LeaderLine::with_points(&points);
        assert_eq!(leader.point_count(), 3);
        assert!((leader.length() - 20.0).abs() < 1e-10);
    }

    #[test]
    fn test_leader_line_add_point() {
        let mut leader = LeaderLine::new();
        leader.add_point(Point::new(0.0, 0.0, 0.0));
        leader.add_point(Point::new(10.0, 0.0, 0.0));
        assert_eq!(leader.point_count(), 2);
        assert!((leader.length() - 10.0).abs() < 1e-10);
    }

    #[test]
    fn test_arrowhead() {
        let arrowhead = Arrowhead::new()
            .with_position(Point::new(100.0, 100.0, 0.0))
            .with_size(3.0)
            .with_type(ArrowheadType::ArrowClosedFilled);

        assert!((arrowhead.position.x - 100.0).abs() < 1e-10);
        assert_eq!(arrowhead.size, 3.0);
    }

    #[test]
    fn test_multileader() {
        let mut mleader = Multileader::new();
        let leader = LeaderLine::with_points(&[
            Point::new(0.0, 0.0, 0.0),
            Point::new(5.0, 0.0, 0.0),
            Point::new(10.0, 10.0, 0.0),
        ]);
        mleader.add_leader(leader);
        assert_eq!(mleader.leader_count(), 1);
        assert!(!mleader.is_empty());
    }

    #[test]
    fn test_multileader_builder() {
        let mut builder = MultileaderBuilder::new();
        builder.text("Test Label");
        builder.set_dogleg_length(10.0);
        builder.set_branch_angle(90.0_f64.to_radians());

        let mleader = builder.build();
        assert_eq!(mleader.get_text(), Some("Test Label"));
        assert!((mleader.dogleg_length - 10.0).abs() < 1e-10);
    }

    #[test]
    fn test_multileader_content() {
        assert!(MultileaderContent::mtext("Test").is_mtext());
        assert!(!MultileaderContent::mtext("Test").is_block());

        assert!(MultileaderContent::block("MyBlock").is_block());
        assert!(!MultileaderContent::block("MyBlock").is_mtext());
    }

    #[test]
    fn test_multileader_style() {
        let style = MultileaderStyle::new("TestStyle");
        assert_eq!(style.name, "TestStyle");
        assert_eq!(style.arrowhead_size, 2.5);
    }

    #[test]
    fn test_multileader_style_operations() {
        let mut style = MultileaderStyle::new("TestStyle");
        style.set_arrowhead_type(ArrowheadType::Dot);
        style.set_arrowhead_size(5.0);
        style.set_text_height(3.0);
        assert_eq!(style.arrowhead_type, ArrowheadType::Dot);
        assert!((style.arrowhead_size - 5.0).abs() < 1e-10);
        assert!((style.text_height - 3.0).abs() < 1e-10);
    }

    #[test]
    fn test_multileader_manager() {
        let manager = MultileaderManager::new();
        assert!(manager.count() == 0);
        assert!(manager.get_style("Standard").is_some());
    }

    #[test]
    fn test_multileader_manager_operations() {
        let mut manager = MultileaderManager::new();
        let object_id = manager.create();

        assert_eq!(manager.count(), 1);
        assert!(manager.get(&object_id).is_some());

        assert!(manager.remove(&object_id));
        assert_eq!(manager.count(), 0);
    }

    #[test]
    fn test_multileader_style_management() {
        let mut manager = MultileaderManager::new();
        let mut style = MultileaderStyle::new("Custom");
        style.description = "Custom multileader style";
        assert!(manager.add_style(style));
        assert!(manager.get_style("Custom").is_some());

        assert_eq!(manager.set_style("Custom"), true);
        assert_eq!(manager.current_style(), "Custom");
    }

    #[test]
    fn test_multileader_text_content() {
        let mut mleader = Multileader::new();
        mleader.set_text("Hello\nWorld");
        assert_eq!(mleader.get_text(), Some("Hello\nWorld"));

        mleader.set_text("Updated");
        assert_eq!(mleader.get_text(), Some("Updated"));
    }

    #[test]
    fn test_leader_types() {
        let straight_leader = LeaderLine::with_points(&[
            Point::new(0.0, 0.0, 0.0),
            Point::new(10.0, 0.0, 0.0),
        ]);
        assert_eq!(straight_leader.leader_type, LeaderType::Straight);
    }

    #[test]
    fn test_multileader_rebuild() {
        let mut mleader = Multileader::new();
        let leader = LeaderLine::with_points(&[
            Point::new(0.0, 0.0, 0.0),
            Point::new(10.0, 0.0, 0.0),
        ]);
        mleader.add_leader(leader);
        mleader.dogleg_length = 8.0;
        mleader.branch_angle = 90.0_f64.to_radians();
        mleader.last_leader_point = Point::new(10.0, 0.0, 0.0);

        mleader.rebuild_leaders();

        if let Some(leader) = mleader.leaders.first() {
            assert!(leader.point_count() >= 3);
        }
    }
}
