use serde::{Serialize, Deserialize};
use std::collections::{HashMap, HashSet};
use std::path::PathBuf;
use std::fmt;
use std::time::{SystemTime, Duration};

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum XrefType {
    Dwg,
    Dwf,
    Dxf,
    Pdf,
    Image,
    Dgn,
    Scene,
}

impl Default for XrefType {
    fn default() -> Self {
        XrefType::Dwg
    }
}

impl XrefType {
    pub fn from_extension(ext: &str) -> Self {
        match ext.to_lowercase().as_str() {
            ".dwg" => XrefType::Dwg,
            ".dwf" | ".dwfx" => XrefType::Dwf,
            ".dxf" => XrefType::Dxf,
            ".pdf" => XrefType::Pdf,
            ".jpg" | ".jpeg" | ".png" | ".bmp" | ".tif" | ".tiff" | ".gif" | ".webp" => XrefType::Image,
            ".dgn" => XrefType::Dgn,
            ".3ds" | ".obj" | ".fbx" => XrefType::Scene,
            _ => XrefType::Dwg,
        }
    }

    pub fn extension(&self) -> &str {
        match self {
            XrefType::Dwg => ".dwg",
            XrefType::Dwf => ".dwf",
            XrefType::Dxf => ".dxf",
            XrefType::Pdf => ".pdf",
            XrefType::Image => ".jpg",
            XrefType::Dgn => ".dgn",
            XrefType::Scene => ".obj",
        }
    }
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum XrefStatus {
    Loaded,
    Unloaded,
    Unresolved,
    Modified,
    Referenced,
    Embedded,
    Overlay,
}

impl Default for XrefStatus {
    fn default() -> Self {
        XrefStatus::Unloaded
    }
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum XrefFormat {
    Full,
    Partial,
    SymbolTableOnly,
    NoMessages,
}

impl Default for XrefFormat {
    fn default() -> Self {
        XrefFormat::Full
    }
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum BindType {
    Bind,
    Insert,
    BindNested,
}

impl Default for BindType {
    fn default() -> Self {
        BindType::Insert
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct XrefDefinition {
    pub name: String,
    pub path: PathBuf,
    pub xref_type: XrefType,
    pub status: XrefStatus,
    pub format: XrefFormat,
    pub loaded_at: Option<SystemTime>,
    pub file_size: u64,
    pub last_modified: SystemTime,
    pub definition_created: SystemTime,
    pub blocks: Vec<String>,
    pub layers: Vec<String>,
    pub linetypes: Vec<String>,
    pub text_styles: Vec<String>,
    pub dimension_styles: Vec<String>,
    pub user_data: HashMap<String, String>,
    pub is_overlay: bool,
    pub is_nested: bool,
    pub attachment_point: AttachmentPoint,
    pub scale: (f64, f64, f64),
    pub rotation: f64,
}

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

impl XrefDefinition {
    pub fn new() -> Self {
        Self {
            name: String::new(),
            path: PathBuf::new(),
            xref_type: XrefType::Dwg,
            status: XrefStatus::Unloaded,
            format: XrefFormat::Full,
            loaded_at: None,
            file_size: 0,
            last_modified: SystemTime::UNIX_EPOCH,
            definition_created: SystemTime::UNIX_EPOCH,
            blocks: Vec::new(),
            layers: Vec::new(),
            linetypes: Vec::new(),
            text_styles: Vec::new(),
            dimension_styles: Vec::new(),
            user_data: HashMap::new(),
            is_overlay: false,
            is_nested: false,
            attachment_point: AttachmentPoint::WorldCoordinateSystem,
            scale: (1.0, 1.0, 1.0),
            rotation: 0.0,
        }
    }

    pub fn with_name(mut self, name: &str) -> Self {
        self.name = name.to_string();
        self
    }

    pub fn with_path(mut self, path: &str) -> Self {
        self.path = PathBuf::from(path);
        self.xref_type = XrefType::from_extension(path);
        self
    }

    pub fn with_scale(mut self, x: f64, y: f64, z: f64) -> Self {
        self.scale = (x, y, z);
        self
    }

    pub fn with_rotation(mut self, rotation: f64) -> Self {
        self.rotation = rotation;
        self
    }

    pub fn set_overlay(&mut self, is_overlay: bool) {
        self.is_overlay = is_overlay;
    }

    pub fn set_format(&mut self, format: XrefFormat) {
        self.format = format;
    }
}

impl fmt::Display for XrefDefinition {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "XREF: {} ({:?}) - {:?}",
            self.name, self.xref_type, self.status
        )
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum AttachmentPoint {
    WorldCoordinateSystem,
    CurrentUcs,
    CurrentViewport,
}

impl Default for AttachmentPoint {
    fn default() -> Self {
        AttachmentPoint::WorldCoordinateSystem
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct XrefInstance {
    pub id: String,
    pub definition_name: String,
    pub position: crate::geometry::Point,
    pub rotation: f64,
    pub scale: (f64, f64, f64),
    pub layer: String,
    pub is_visible: bool,
    pub is_clipped: bool,
    pub clip_boundary: Option<Vec<crate::geometry::Point>>,
    pub transparency: f64,
    pub brightness: f64,
    pub contrast: f64,
    pub fade: f64,
    pub is_frozen: bool,
    pub is_locked: bool,
}

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

impl XrefInstance {
    pub fn new() -> Self {
        Self {
            id: uuid::Uuid::new_v4().to_string(),
            definition_name: String::new(),
            position: crate::geometry::Point::origin(),
            rotation: 0.0,
            scale: (1.0, 1.0, 1.0),
            layer: String::new(),
            is_visible: true,
            is_clipped: false,
            clip_boundary: None,
            transparency: 0.0,
            brightness: 50.0,
            contrast: 50.0,
            fade: 0.0,
            is_frozen: false,
            is_locked: false,
        }
    }

    pub fn with_definition(mut self, name: &str) -> Self {
        self.definition_name = name.to_string();
        self
    }

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

    pub fn with_rotation(mut self, rotation: f64) -> Self {
        self.rotation = rotation;
        self
    }

    pub fn with_scale(mut self, x: f64, y: f64, z: f64) -> Self {
        self.scale = (x, y, z);
        self
    }

    pub fn set_clip_boundary(&mut self, boundary: &[crate::geometry::Point]) {
        self.clip_boundary = Some(boundary.to_vec());
        self.is_clipped = true;
    }

    pub fn clear_clip_boundary(&mut self) {
        self.clip_boundary = None;
        self.is_clipped = false;
    }

    pub fn set_visibility(&mut self, visible: bool) {
        self.is_visible = visible;
    }

    pub fn set_layer(&mut self, layer: &str) {
        self.layer = layer.to_string();
    }

    pub fn set_transparency(&mut self, transparency: f64) {
        self.transparency = transparency.clamp(0.0, 100.0);
    }

    pub fn set_freeze(&mut self, frozen: bool) {
        self.is_frozen = frozen;
    }

    pub fn set_lock(&mut self, locked: bool) {
        self.is_locked = locked;
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct XrefPath {
    pub relative_path: PathBuf,
    pub absolute_path: PathBuf,
    pub found: bool,
    pub last_checked: SystemTime,
}

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

impl XrefPath {
    pub fn new() -> Self {
        Self {
            relative_path: PathBuf::new(),
            absolute_path: PathBuf::new(),
            found: false,
            last_checked: SystemTime::UNIX_EPOCH,
        }
    }

    pub fn from_relative(relative: &str, base: &str) -> Self {
        let relative_path = PathBuf::from(relative);
        let absolute_path = PathBuf::from(base).parent()
            .unwrap_or(PathBuf::from("."))
            .join(&relative_path);

        Self {
            relative_path,
            absolute_path,
            found: false,
            last_checked: SystemTime::UNIX_EPOCH,
        }
    }

    pub fn from_absolute(path: &str) -> Self {
        let absolute_path = PathBuf::from(path);
        Self {
            relative_path: absolute_path.file_name()
                .map(|p| PathBuf::from(p.to_string_lossy().as_ref()))
                .unwrap_or_else(|| absolute_path.clone()),
            absolute_path,
            found: false,
            last_checked: SystemTime::UNIX_EPOCH,
        }
    }

    pub fn exists(&mut self) -> bool {
        self.found = self.absolute_path.exists();
        self.last_checked = SystemTime::now();
        self.found
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NestedXref {
    pub path: PathBuf,
    pub definition_name: String,
    pub parent_xref: String,
    pub depth: u32,
    pub is_valid: bool,
}

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

impl NestedXref {
    pub fn new() -> Self {
        Self {
            path: PathBuf::new(),
            definition_name: String::new(),
            parent_xref: String::new(),
            depth: 0,
            is_valid: false,
        }
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct XrefDependency {
    pub file_name: String,
    pub path: PathBuf,
    pub is_required: bool,
    pub is_missing: bool,
}

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

impl XrefDependency {
    pub fn new() -> Self {
        Self {
            file_name: String::new(),
            path: PathBuf::new(),
            is_required: true,
            is_missing: false,
        }
    }
}

#[derive(Debug, Clone)]
pub struct XrefManager {
    definitions: HashMap<String, XrefDefinition>,
    instances: HashMap<String, XrefInstance>,
    paths: HashMap<String, XrefPath>,
    nested_xrefs: Vec<NestedXref>,
    dependencies: Vec<XrefDependency>,
    search_paths: Vec<PathBuf>,
    is_attach_relative: bool,
    is_load_on_demand: bool,
    max_nested_depth: u32,
    current_nested_depth: u32,
}

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

impl XrefManager {
    pub fn new() -> Self {
        Self {
            definitions: HashMap::new(),
            instances: HashMap::new(),
            paths: HashMap::new(),
            nested_xrefs: Vec::new(),
            dependencies: Vec::new(),
            search_paths: Vec::new(),
            is_attach_relative: true,
            is_load_on_demand: false,
            max_nested_depth: 10,
            current_nested_depth: 0,
        }
    }

    pub fn attach(
        &mut self,
        name: &str,
        path: &str,
        position: crate::geometry::Point,
        rotation: f64,
        scale: (f64, f64, f64),
    ) -> Result<String, String> {
        let definition = XrefDefinition::with_name(name)
            .with_path(path)
            .with_scale(scale.0, scale.1, scale.2)
            .with_rotation(rotation);

        let instance_id = self.create_instance(&definition.name, position, rotation, scale)?;

        self.definitions.insert(name.to_string(), definition);

        Ok(instance_id)
    }

    pub fn attach_overlay(&mut self, name: &str, path: &str) -> Result<String, String> {
        let mut definition = XrefDefinition::with_name(name).with_path(path)?;
        definition.set_overlay(true);

        let instance_id = self.create_instance(name, crate::geometry::Point::origin(), 0.0, (1.0, 1.0, 1.0))?;

        self.definitions.insert(name.to_string(), definition);

        Ok(instance_id)
    }

    fn create_instance(
        &mut self,
        definition_name: &str,
        position: crate::geometry::Point,
        rotation: f64,
        scale: (f64, f64, f64),
    ) -> Result<String, String> {
        let instance = XrefInstance::new()
            .with_definition(definition_name)
            .with_position(position)
            .with_rotation(rotation)
            .with_scale(scale.0, scale.1, scale.2);

        let instance_id = instance.id.clone();
        self.instances.insert(instance_id.clone(), instance);

        Ok(instance_id)
    }

    pub fn detach(&mut self, name: &str) -> bool {
        let removed_def = self.definitions.remove(name);
        let removed_instances: Vec<String> = self.instances.iter()
            .filter(|(_, i)| i.definition_name == name)
            .map(|(id, _)| id.clone())
            .collect();

        for id in &removed_instances {
            self.instances.remove(id);
        }

        removed_def.is_some() || !removed_instances.is_empty()
    }

    pub fn reload(&mut self, name: &str) -> Result<(), String> {
        if let Some(definition) = self.definitions.get_mut(name) {
            definition.loaded_at = Some(SystemTime::now());
            definition.status = XrefStatus::Loaded;

            for instance in self.instances.values_mut() {
                if instance.definition_name == name {
                    instance.clear_clip_boundary();
                }
            }

            Ok(())
        } else {
            Err(format!("XREF '{}' not found", name))
        }
    }

    pub fn unload(&mut self, name: &str) -> Result<(), String> {
        if let Some(definition) = self.definitions.get_mut(name) {
            definition.status = XrefStatus::Unloaded;
            definition.loaded_at = None;

            Ok(())
        } else {
            Err(format!("XREF '{}' not found", name))
        }
    }

    pub fn bind(&mut self, name: &str, bind_type: BindType) -> Result<(), String> {
        if !self.definitions.contains_key(name) {
            return Err(format!("XREF '{}' not found", name));
        }

        self.detach(name)?;

        match bind_type {
            BindType::Insert => {
            }
            BindType::Bind => {
            }
            BindType::BindNested => {
            }
        }

        Ok(())
    }

    pub fn rename(&mut self, old_name: &str, new_name: &str) -> bool {
        if let Some(definition) = self.definitions.remove(old_name) {
            let mut new_definition = definition;
            new_definition.name = new_name.to_string();

            for instance in self.instances.values_mut() {
                if instance.definition_name == old_name {
                    instance.definition_name = new_name.to_string();
                }
            }

            self.definitions.insert(new_name.to_string(), new_definition);
            true
        } else {
            false
        }
    }

    pub fn get_definition(&self, name: &str) -> Option<&XrefDefinition> {
        self.definitions.get(name)
    }

    pub fn get_definition_mut(&mut self, name: &str) -> Option<&mut XrefDefinition> {
        self.definitions.get_mut(name)
    }

    pub fn get_instance(&self, id: &str) -> Option<&XrefInstance> {
        self.instances.get(id)
    }

    pub fn get_instance_mut(&mut self, id: &str) -> Option<&mut XrefInstance> {
        self.instances.get_mut(id)
    }

    pub fn get_instances_by_definition(&self, name: &str) -> Vec<&XrefInstance> {
        self.instances.values()
            .filter(|i| i.definition_name == name)
            .collect()
    }

    pub fn definition_count(&self) -> usize {
        self.definitions.len()
    }

    pub fn instance_count(&self) -> usize {
        self.instances.len()
    }

    pub fn definition_names(&self) -> Vec<&str> {
        self.definitions.keys().map(|s| s.as_str()).collect()
    }

    pub fn instance_ids(&self) -> Vec<&str> {
        self.instances.keys().map(|s| s.as_str()).collect()
    }

    pub fn add_search_path(&mut self, path: &str) {
        self.search_paths.push(PathBuf::from(path));
    }

    pub fn clear_search_paths(&mut self) {
        self.search_paths.clear();
    }

    pub fn resolve_path(&mut self, filename: &str) -> Option<PathBuf> {
        let mut tried_paths = Vec::new();

        for search_path in &self.search_paths {
            let candidate = search_path.join(filename);
            tried_paths.push(candidate.clone());
            if candidate.exists() {
                return Some(candidate);
            }
        }

        let current_dir = PathBuf::from(".");
        for path in &tried_paths {
            if path.exists() {
                return Some(path.clone());
            }
        }

        None
    }

    pub fn find_missing_xrefs(&self) -> Vec<&str> {
        self.definitions.values()
            .filter(|d| d.status == XrefStatus::Unresolved)
            .map(|d| d.name.as_str())
            .collect()
    }

    pub fn set_relative_path(&mut self, relative: bool) {
        self.is_attach_relative = relative;
    }

    pub fn set_load_on_demand(&mut self, load: bool) {
        self.is_load_on_demand = load;
    }

    pub fn set_clip_boundary(&mut self, instance_id: &str, boundary: &[crate::geometry::Point]) -> bool {
        if let Some(instance) = self.instances.get_mut(instance_id) {
            instance.set_clip_boundary(boundary);
            true
        } else {
            false
        }
    }

    pub fn remove_clip_boundary(&mut self, instance_id: &str) -> bool {
        if let Some(instance) = self.instances.get_mut(instance_id) {
            instance.clear_clip_boundary();
            true
        } else {
            false
        }
    }

    pub fn update_path(&mut self, name: &str, new_path: &str) -> bool {
        if let Some(definition) = self.definitions.get_mut(name) {
            definition.path = PathBuf::from(new_path);
            definition.xref_type = XrefType::from_extension(new_path);
            definition.status = XrefStatus::Modified;
            true
        } else {
            false
        }
    }

    pub fn verify_all_paths(&mut self) -> Vec<String> {
        let mut missing = Vec::new();

        let names: Vec<String> = self.definition_names().into_iter().map(|s| s.to_string()).collect();
        for name in names {
            if let Some(path) = self.paths.get_mut(&name) {
                if !path.exists() {
                    missing.push(name);
                }
            }
        }

        missing
    }

    pub fn set_visibility(&mut self, name: &str, visible: bool) -> usize {
        let mut count = 0;
        for instance in self.instances.values_mut() {
            if instance.definition_name == name {
                instance.set_visibility(visible);
                count += 1;
            }
        }
        count
    }

    pub fn freeze_all(&mut self) {
        for instance in self.instances.values_mut() {
            instance.set_freeze(true);
        }
    }

    pub fn unfreeze_all(&mut self) {
        for instance in self.instances.values_mut() {
            instance.set_freeze(false);
        }
    }

    pub fn lock_all(&mut self) {
        for instance in self.instances.values_mut() {
            instance.set_lock(true);
        }
    }

    pub fn unlock_all(&mut self) {
        for instance in self.instances.values_mut() {
            instance.set_lock(false);
        }
    }

    pub fn clear(&mut self) {
        self.definitions.clear();
        self.instances.clear();
        self.paths.clear();
        self.nested_xrefs.clear();
        self.dependencies.clear();
    }

    pub fn dump_xref_tree(&self, name: &str, depth: u32) -> Vec<(String, u32)> {
        let mut tree = Vec::new();
        tree.push((name.to_string(), depth));

        if depth < self.max_nested_depth {
            if let Some(definition) = self.definitions.get(name) {
                for nested in &definition.blocks {
                    tree.extend(self.dump_xref_tree(nested, depth + 1));
                }
            }
        }

        tree
    }

    pub fn get_statistics(&self) -> XrefStatistics {
        let mut loaded = 0;
        let mut unloaded = 0;
        let mut unresolved = 0;
        let mut modified = 0;

        for definition in self.definitions.values() {
            match definition.status {
                XrefStatus::Loaded => loaded += 1,
                XrefStatus::Unloaded => unloaded += 1,
                XrefStatus::Unresolved => unresolved += 1,
                XrefStatus::Modified => modified += 1,
                _ => {}
            }
        }

        XrefStatistics {
            total_definitions: self.definitions.len(),
            total_instances: self.instances.len(),
            loaded,
            unloaded,
            unresolved,
            modified,
            search_paths: self.search_paths.len(),
        }
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct XrefStatistics {
    pub total_definitions: usize,
    pub total_instances: usize,
    pub loaded: usize,
    pub unloaded: usize,
    pub unresolved: usize,
    pub modified: usize,
    pub search_paths: usize,
}

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

    #[test]
    fn test_xref_definition_creation() {
        let xref = XrefDefinition::with_name("MyXref")
            .with_path("reference.dwg")
            .with_scale(2.0, 2.0, 2.0)
            .with_rotation(45.0);

        assert_eq!(xref.name, "MyXref");
        assert_eq!(xref.xref_type, XrefType::Dwg);
        assert!((xref.scale.0 - 2.0).abs() < 1e-10);
        assert!((xref.rotation - 45.0).abs() < 1e-10);
    }

    #[test]
    fn test_xref_instance_creation() {
        let instance = XrefInstance::new()
            .with_definition("MyXref")
            .with_position(Point::new(100.0, 100.0, 0.0))
            .with_rotation(90.0)
            .with_scale(1.0, 2.0, 1.0);

        assert_eq!(instance.definition_name, "MyXref");
        assert!((instance.position.x - 100.0).abs() < 1e-10);
    }

    #[test]
    fn test_xref_manager_attach() {
        let mut manager = XrefManager::new();
        let result = manager.attach(
            "TestXref",
            "reference.dwg",
            Point::new(0.0, 0.0, 0.0),
            0.0,
            (1.0, 1.0, 1.0),
        );

        assert!(result.is_ok());
        let instance_id = result.unwrap();
        assert!(manager.definition_count() == 1);
        assert!(manager.instance_count() == 1);
    }

    #[test]
    fn test_xref_manager_detach() {
        let mut manager = XrefManager::new();
        manager.attach("TestXref", "reference.dwg", Point::origin(), 0.0, (1.0, 1.0, 1.0)).unwrap();

        assert!(manager.detach("TestXref"));
        assert!(manager.definition_count() == 0);
        assert!(manager.instance_count() == 0);
    }

    #[test]
    fn test_xref_manager_rename() {
        let mut manager = XrefManager::new();
        manager.attach("OldName", "reference.dwg", Point::origin(), 0.0, (1.0, 1.0, 1.0)).unwrap();

        assert!(manager.rename("OldName", "NewName"));
        assert!(manager.definition_names().contains(&"NewName"));
        assert!(!manager.definition_names().contains(&"OldName"));
    }

    #[test]
    fn test_xref_path_resolution() {
        let mut manager = XrefManager::new();
        manager.add_search_path("C:/CAD/Files");
        manager.add_search_path("D:/Projects");

        assert!(manager.resolve_path("existing.dwg").is_some());
    }

    #[test]
    fn test_xref_type_detection() {
        assert_eq!(XrefType::from_extension(".dwg"), XrefType::Dwg);
        assert_eq!(XrefType::from_extension(".PDF"), XrefType::Pdf);
        assert_eq!(XrefType::from_extension(".png"), XrefType::Image);
        assert_eq!(XrefType::from_extension(".dgn"), XrefType::Dgn);
    }

    #[test]
    fn test_xref_clip_boundary() {
        let mut instance = XrefInstance::new();
        let boundary = vec![
            Point::new(0.0, 0.0, 0.0),
            Point::new(100.0, 0.0, 0.0),
            Point::new(100.0, 100.0, 0.0),
            Point::new(0.0, 100.0, 0.0),
        ];

        instance.set_clip_boundary(&boundary);

        assert!(instance.is_clipped);
        assert!(instance.clip_boundary.is_some());
        assert_eq!(instance.clip_boundary.unwrap().len(), 4);
    }

    #[test]
    fn test_xref_visibility() {
        let mut instance = XrefInstance::new();
        instance.set_visibility(false);
        assert!(!instance.is_visible);

        instance.set_visibility(true);
        assert!(instance.is_visible);
    }

    #[test]
    fn test_xref_freeze() {
        let mut instance = XrefInstance::new();
        instance.set_freeze(true);
        assert!(instance.is_frozen);
    }

    #[test]
    fn test_xref_transparency() {
        let mut instance = XrefInstance::new();
        instance.set_transparency(50.0);
        assert!((instance.transparency - 50.0).abs() < 1e-10);

        instance.set_transparency(150.0);
        assert!((instance.transparency - 100.0).abs() < 1e-10);
    }

    #[test]
    fn test_xref_overlay() {
        let mut definition = XrefDefinition::new();
        definition.set_overlay(true);
        assert!(definition.is_overlay);
    }

    #[test]
    fn test_xref_format() {
        let mut definition = XrefDefinition::new();
        definition.set_format(XrefFormat::SymbolTableOnly);
        assert_eq!(definition.format, XrefFormat::SymbolTableOnly);
    }

    #[test]
    fn test_xref_path() {
        let path = XrefPath::from_relative("refs/xref.dwg", "C:/Projects/drawing.dwg");
        assert!(path.relative_path.to_string_lossy().contains("xref.dwg"));
    }

    #[test]
    fn test_xref_statistics() {
        let mut manager = XrefManager::new();
        manager.attach("Xref1", "ref1.dwg", Point::origin(), 0.0, (1.0, 1.0, 1.0)).unwrap();
        manager.attach("Xref2", "ref2.dwg", Point::origin(), 0.0, (1.0, 1.0, 1.0)).unwrap();

        let stats = manager.get_statistics();
        assert_eq!(stats.total_definitions, 2);
        assert_eq!(stats.total_instances, 2);
    }

    #[test]
    fn test_xref_reset_path() {
        let mut manager = XrefManager::new();
        manager.attach("Xref", "old.dwg", Point::origin(), 0.0, (1.0, 1.0, 1.0)).unwrap();

        assert!(manager.update_path("Xref", "new.dwg"));
        let definition = manager.get_definition("Xref").unwrap();
        assert!(definition.path.to_string_lossy().contains("new.dwg"));
    }
}
