use crate::data_structure::{Document, Block, Layer, Entity, ObjectId, EntityType, EntityGeometry, Visibility, Transform, HatchBoundary, BoundaryType, HatchEdge, EdgeType, DimensionType, TextStyle, TextAlignment};
use crate::geometry::{Point, Line, Circle, Arc, Ellipse, Polyline, BSpline, NURBS};
use std::io::{Read, Seek, SeekFrom};
use thiserror::Error;
use crate::io::Error as ImportError;

#[derive(Debug, Error)]
pub enum DWGError {
    #[error("Failed to parse DWG file: {0}")]
    ParseError(String),
    
    #[error("Invalid DWG version: {0}")]
    InvalidVersion(String),
    
    #[error("Unsupported DWG version: {0}")]
    UnsupportedVersion(String),
    
    #[error("CRC error: {0}")]
    CRCError(String),
    
    #[error("IO error: {0}")]
    IOError(#[from] std::io::Error),
}

#[derive(Debug, Clone, PartialEq)]
pub enum DWGVersion {
    R12,
    R13,
    R14,
    R2000,
    R2004,
    R2007,
    R2010,
    R2013,
    R2018,
}

impl DWGVersion {
    pub fn from_magic(magic: &[u8]) -> Option<Self> {
        let magic_str = String::from_utf8_lossy(magic);
        if magic_str.contains("AC1009") {
            Some(DWGVersion::R12)
        } else if magic_str.contains("AC1012") {
            Some(DWGVersion::R13)
        } else if magic_str.contains("AC1014") {
            Some(DWGVersion::R14)
        } else if magic_str.contains("AC1015") {
            Some(DWGVersion::R2000)
        } else if magic_str.contains("AC1018") {
            Some(DWGVersion::R2004)
        } else if magic_str.contains("AC1021") {
            Some(DWGVersion::R2007)
        } else if magic_str.contains("AC1024") {
            Some(DWGVersion::R2010)
        } else if magic_str.contains("AC1027") {
            Some(DWGVersion::R2013)
        } else if magic_str.contains("AC1032") {
            Some(DWGVersion::R2018)
        } else {
            None
        }
    }
}

struct DWGEntity {
    entity_type: String,
    handles: Vec<String>,
    string_data: Vec<String>,
    double_data: Vec<f64>,
    int_data: Vec<i32>,
    point_data: Vec<Point>,
}

struct DWGSection {
    section_id: u16,
    size: usize,
    offset: usize,
    compressed: bool,
}

struct DWGParser<'a> {
    data: &'a [u8],
    cursor: usize,
    version: DWGVersion,
    entities: Vec<Entity>,
    layers: Vec<(String, ObjectId)>,
    blocks: Vec<Block>,
    block_names: Vec<String>,
    current_block: Option<String>,
    object_map: std::collections::HashMap<String, DWGEntity>,
    entity_handles: std::collections::HashMap<String, usize>,
}

impl<'a> DWGParser<'a> {
    fn new(data: &'a [u8]) -> Self {
        Self {
            data,
            cursor: 0,
            version: DWGVersion::R12,
            entities: Vec::new(),
            layers: Vec::new(),
            blocks: Vec::new(),
            block_names: Vec::new(),
            current_block: None,
            object_map: std::collections::HashMap::new(),
            entity_handles: std::collections::HashMap::new(),
        }
    }

    fn read_u8(&mut self) -> Result<u8, DWGError> {
        if self.cursor >= self.data.len() {
            return Err(DWGError::ParseError("EOF reached".to_string()));
        }
        let value = self.data[self.cursor];
        self.cursor += 1;
        Ok(value)
    }

    fn read_u16(&mut self) -> Result<u16, DWGError> {
        if self.cursor + 1 >= self.data.len() {
            return Err(DWGError::ParseError("EOF reached".to_string()));
        }
        let value = u16::from_le_bytes([self.data[self.cursor], self.data[self.cursor + 1]]);
        self.cursor += 2;
        Ok(value)
    }

    fn read_u32(&mut self) -> Result<u32, DWGError> {
        if self.cursor + 3 >= self.data.len() {
            return Err(DWGError::ParseError("EOF reached".to_string()));
        }
        let value = u32::from_le_bytes([
            self.data[self.cursor],
            self.data[self.cursor + 1],
            self.data[self.cursor + 2],
            self.data[self.cursor + 3],
        ]);
        self.cursor += 4;
        Ok(value)
    }

    fn read_f64(&mut self) -> Result<f64, DWGError> {
        if self.cursor + 7 >= self.data.len() {
            return Err(DWGError::ParseError("EOF reached".to_string()));
        }
        let bytes: [u8; 8] = [
            self.data[self.cursor],
            self.data[self.cursor + 1],
            self.data[self.cursor + 2],
            self.data[self.cursor + 3],
            self.data[self.cursor + 4],
            self.data[self.cursor + 5],
            self.data[self.cursor + 6],
            self.data[self.cursor + 7],
        ];
        let value = f64::from_le_bytes(bytes);
        self.cursor += 8;
        Ok(value)
    }

    fn read_string(&mut self, length: usize) -> Result<String, DWGError> {
        if self.cursor + length >= self.data.len() {
            return Err(DWGError::ParseError("EOF reached".to_string()));
        }
        let bytes = &self.data[self.cursor..self.cursor + length];
        self.cursor += length;
        let s = String::from_utf8_lossy(bytes).trim_end_matches('\0').to_string();
        Ok(s)
    }

    fn read_crc(&mut self) -> Result<u16, DWGError> {
        self.read_u16()
    }

    fn verify_crc(&self, start: usize, end: usize, expected: u16) -> bool {
        let mut crc: u16 = 0;
        for i in start..end {
            crc ^= self.data[i] as u16;
            for _ in 0..8 {
                if crc & 1 != 0 {
                    crc = (crc >> 1) ^ 0xA001;
                } else {
                    crc >>= 1;
                }
            }
        }
        crc == expected
    }

    fn parse_version(&mut self) -> Result<(), DWGError> {
        if self.cursor + 6 > self.data.len() {
            return Err(DWGError::ParseError("File too small".to_string()));
        }
        
        let magic = &self.data[self.cursor..self.cursor + 6];
        if let Some(version) = DWGVersion::from_magic(magic) {
            self.version = version;
            self.cursor += 6;
            Ok(())
        } else {
            Err(DWGError::InvalidVersion("Unknown".to_string()))
        }
    }

    fn parse_header_section(&mut self) -> Result<(), DWGError> {
        let section_id = self.read_u16()?;
        let section_size = self.read_u32()? as usize;
        let section_start = self.cursor;
        
        match self.version {
            DWGVersion::R12 | DWGVersion::R13 | DWGVersion::R14 => {
                self.parse_header_variables()?;
            }
            DWGVersion::R2000 | DWGVersion::R2004 | DWGVersion::R2007 | 
            DWGVersion::R2010 | DWGVersion::R2013 | DWGVersion::R2018 => {
                self.parse_section_header()?;
                self.parse_header_variables()?;
            }
        }
        
        self.cursor = section_start + section_size;
        Ok(())
    }

    fn parse_section_header(&mut self) -> Result<(), DWGError> {
        let section_number = self.read_u16()?;
        let section_name_length = self.read_u8()?;
        let _section_name = self.read_string(section_name_length as usize)?;
        let page_count = self.read_u32()?;
        let _page_size = self.read_u32()?;
        let _ = self.read_u32()?;
        Ok(())
    }

    fn parse_header_variables(&mut self) -> Result<(), DWGError> {
        while self.cursor < self.data.len() - 2 {
            let marker = self.read_u8()?;
            if marker == 0x0D || marker == 0x0A {
                continue;
            }
            if marker == 0x03 || marker == 0x3D {
                break;
            }
            
            self.cursor -= 1;
            let data = self.read_string(64)?;
            if data.contains("$ACADVER") {
                if let Some(start) = data.find('$') {
                    if let Some(end) = data[start..].find(|c: char| !c.is_ascii_alphanumeric()) {
                        let version_str = &data[start + 1..start + end];
                        self.cursor -= 1;
                        return Ok(());
                    }
                }
            }
        }
        Ok(())
    }

    fn parse_classes_section(&mut self) -> Result<(), DWGError> {
        let section_size = self.read_u32()? as usize;
        let section_start = self.cursor;
        let class_count = self.read_u32()?;
        
        for _ in 0..class_count {
            let class_num = self.read_u16()?;
            let class_name = self.read_string(64)?;
            let app_name = self.read_string(64)?;
            let _flags = self.read_u8()?;
            let _was_proxy = self.read_u8()?;
        }
        
        self.cursor = section_start + section_size;
        Ok(())
    }

    fn parse_tables_section(&mut self) -> Result<(), DWGError> {
        match self.version {
            DWGVersion::R12 | DWGVersion::R13 | DWGVersion::R14 => {
                self.parse_tables_section_legacy()?;
            }
            _ => {
                self.parse_tables_section_modern()?;
            }
        }
        Ok(())
    }

    fn parse_tables_section_legacy(&mut self) -> Result<(), DWGError> {
        let table_count = self.read_u16()?;
        
        for _ in 0..table_count {
            let table_type = self.read_string(64)?;
            let max_entries = self.read_u16()?;
            let entry_count = self.read_u16()?;
            
            match table_type.as_str() {
                "LAYER" => {
                    for _ in 0..entry_count {
                        let layer_name = self.read_string(64)?;
                        let flags = self.read_u8()?;
                        let _color = self.read_u16()?;
                        let _linetype = self.read_string(64)?;
                        self.layers.push((layer_name, ObjectId::new()));
                    }
                }
                "BLOCK" => {
                    for _ in 0..entry_count {
                        let block_name = self.read_string(64)?;
                        self.block_names.push(block_name);
                    }
                }
                _ => {
                    for _ in 0..entry_count {
                        let _name = self.read_string(64)?;
                    }
                }
            }
        }
        Ok(())
    }

    fn parse_tables_section_modern(&mut self) -> Result<(), DWGError> {
        let section_id = self.read_u16()?;
        let _section_size = self.read_u32()?;
        
        let layer_table_size = self.read_u32()?;
        let _layer_table_start = self.cursor;
        self.cursor += layer_table_size as usize;
        
        let block_table_size = self.read_u32()?;
        let _block_table_start = self.cursor;
        self.cursor += block_table_size as usize;
        
        Ok(())
    }

    fn parse_blocks_section(&mut self) -> Result<(), DWGError> {
        let section_size = self.read_u32()? as usize;
        let section_start = self.cursor;
        
        let num_blocks = self.read_u16()?;
        
        for _ in 0..num_blocks {
            let block_name = self.read_string(64)?;
            let _flags = self.read_u8()?;
            let _layer = self.read_u16()?;
            let _base_point = self.read_f64()?;
            let _base_point_y = self.read_f64()?;
            let _base_point_z = self.read_f64()?;
            let _block_type = self.read_u16()?;
            
            let entity_count = self.read_u16()?;
            
            self.current_block = Some(block_name.clone());
            let mut block = Block::new(block_name);
            
            for _ in 0..entity_count {
                if let Some(entity) = self.parse_entity()? {
                    block.add_entity(entity);
                }
            }
            
            self.blocks.push(block);
        }
        
        self.cursor = section_start + section_size;
        Ok(())
    }

    fn parse_entities_section(&mut self) -> Result<(), DWGError> {
        let section_size = self.read_u32()? as usize;
        let section_start = self.cursor;
        
        match self.version {
            DWGVersion::R12 | DWGVersion::R13 | DWGVersion::R14 => {
                self.parse_entities_legacy()?;
            }
            _ => {
                self.parse_entities_modern()?;
            }
        }
        
        self.cursor = section_start + section_size;
        Ok(())
    }

    fn parse_entities_legacy(&mut self) -> Result<(), DWGError> {
        let num_entities = self.read_u16()?;
        
        for _ in 0..num_entities {
            if let Some(entity) = self.parse_entity()? {
                self.entities.push(entity);
            }
        }
        Ok(())
    }

    fn parse_entities_modern(&mut self) -> Result<(), DWGError> {
        loop {
            let entity_type_id = self.read_u16()?;
            if entity_type_id == 0 {
                break;
            }
            
            if let Some(entity) = self.parse_entity_by_type(entity_type_id)? {
                self.entities.push(entity);
            }
        }
        Ok(())
    }

    fn parse_entity(&mut self) -> Result<Option<Entity>, DWGError> {
        let handle = self.read_u8()?;
        let entity_type_id = self.read_u16()?;
        
        self.parse_entity_by_type(entity_type_id)
    }

    fn parse_entity_by_type(&mut self, entity_type_id: u16) -> Result<Option<Entity>, DWGError> {
        match entity_type_id {
            1 => self.parse_line_entity(),
            2 => self.parse_circle_entity(),
            3 => self.parse_arc_entity(),
            4 => self.parse_text_entity(),
            5 => self.parse_dimension_entity(),
            6 => self.parse_insert_entity(),
            7 => self.parse_polyline_entity(),
            8 => self.parse_spline_entity(),
            9 => self.parse_hatch_entity(),
            10 => self.parse_ellipse_entity(),
            11 => self.parse_point_entity(),
            12 => self.parse_lwpolyline_entity(),
            _ => {
                let _size = self.read_u16()?;
                Ok(None)
            }
        }
    }

    fn parse_line_entity(&mut self) -> Result<Option<Entity>, DWGError> {
        let start = Point::new(
            self.read_f64()?,
            self.read_f64()?,
            self.read_f64()?,
        );
        let end = Point::new(
            self.read_f64()?,
            self.read_f64()?,
            self.read_f64()?,
        );
        let _thickness = self.read_f64()?;
        let _extrusion = self.read_f64()?;
        
        let line = Line::new(start, end);
        Ok(Some(Entity::new(
            EntityType::Line,
            EntityGeometry::Line(line),
        )))
    }

    fn parse_circle_entity(&mut self) -> Result<Option<Entity>, DWGError> {
        let center = Point::new(
            self.read_f64()?,
            self.read_f64()?,
            self.read_f64()?,
        );
        let radius = self.read_f64()?;
        let _thickness = self.read_f64()?;
        let _extrusion = self.read_f64()?;
        
        let circle = Circle::new(center, radius);
        Ok(Some(Entity::new(
            EntityType::Circle,
            EntityGeometry::Circle(circle),
        )))
    }

    fn parse_arc_entity(&mut self) -> Result<Option<Entity>, DWGError> {
        let center = Point::new(
            self.read_f64()?,
            self.read_f64()?,
            self.read_f64()?,
        );
        let radius = self.read_f64()?;
        let start_angle = self.read_f64()?;
        let end_angle = self.read_f64()?;
        let _thickness = self.read_f64()?;
        let _extrusion = self.read_f64()?;
        
        let arc = Arc::new(center, radius, start_angle, end_angle);
        Ok(Some(Entity::new(
            EntityType::Arc,
            EntityGeometry::Arc(arc),
        )))
    }

    fn parse_ellipse_entity(&mut self) -> Result<Option<Entity>, DWGError> {
        let center = Point::new(
            self.read_f64()?,
            self.read_f64()?,
            self.read_f64()?,
        );
        let major_x = self.read_f64()?;
        let major_y = self.read_f64()?;
        let major_z = self.read_f64()?;
        let major_length = (major_x * major_x + major_y * major_y + major_z * major_z).sqrt();
        let ratio = self.read_f64()?;
        let start_angle = self.read_f64()?;
        let end_angle = self.read_f64()?;
        
        let minor_length = major_length * ratio;
        let rotation = if major_x.abs() > major_y.abs() {
            (major_y / major_x).atan()
        } else if major_y != 0.0 {
            std::f64::consts::PI / 2.0 - (major_x / major_y).atan()
        } else {
            0.0
        };
        
        let ellipse = Ellipse::new(center, major_length / 2.0, minor_length / 2.0, rotation);
        Ok(Some(Entity::new(
            EntityType::Ellipse,
            EntityGeometry::Ellipse(ellipse),
        )))
    }

    fn parse_point_entity(&mut self) -> Result<Option<Entity>, DWGError> {
        let x = self.read_f64()?;
        let y = self.read_f64()?;
        let z = self.read_f64()?;
        
        let point = Point::new(x, y, z);
        Ok(Some(Entity::new(
            EntityType::Point,
            EntityGeometry::Point(point),
        )))
    }

    fn parse_text_entity(&mut self) -> Result<Option<Entity>, DWGError> {
        let insertion_point = Point::new(
            self.read_f64()?,
            self.read_f64()?,
            self.read_f64()?,
        );
        let height = self.read_f64()?;
        let width_factor = self.read_f64()?;
        let rotation = self.read_f64()?;
        let _flags = self.read_u8()?;
        let text_length = self.read_u16()?;
        let content = self.read_string(text_length as usize)?;
        
        Ok(Some(Entity::new(
            EntityType::Text,
            EntityGeometry::Text {
                content,
                position: insertion_point,
                height,
                rotation,
                width_factor: 1.0,
                font_name: "Standard".to_string(),
                style: TextStyle {
                    bold: false,
                    italic: false,
                    underline: false,
                    alignment: TextAlignment::Left,
                },
            },
        )))
    }

    fn parse_dimension_entity(&mut self) -> Result<Option<Entity>, DWGError> {
        let _geometry = self.read_u32()?;
        let _attachment = self.read_u16()?;
        let _line_spacing_style = self.read_u16()?;
        let _line_spacing_factor = self.read_f64()?;
        let _actual_measurement = self.read_f64()?;
        let text_length = self.read_u16()?;
        let content = self.read_string(text_length as usize)?;
        let insertion_point = Point::new(
            self.read_f64()?,
            self.read_f64()?,
            self.read_f64()?,
        );
        let _rotation = self.read_f64()?;
        let _horizontal_direction = self.read_f64()?;
        let _vertical_direction = self.read_f64()?;
        
        Ok(Some(Entity::new(
            EntityType::Dimension,
            EntityGeometry::Dimension {
                dim_type: DimensionType::Linear,
                measurement: 0.0,
                text: content.clone(),
                text_position: insertion_point,
                text_height: 2.5,
                text_rotation: 0.0,
                definition_point: insertion_point,
                def_point_1: insertion_point,
                def_point_2: insertion_point,
                def_point_3: insertion_point,
                def_point_4: insertion_point,
                angle: 0.0,
                extension_lines: true,
                center_marks: false,
            },
        )))
    }

    fn parse_insert_entity(&mut self) -> Result<Option<Entity>, DWGError> {
        let block_name_length = self.read_u16()?;
        let block_name = self.read_string(block_name_length as usize)?;
        let insertion_point = Point::new(
            self.read_f64()?,
            self.read_f64()?,
            self.read_f64()?,
        );
        let scale_x = self.read_f64()?;
        let scale_y = self.read_f64()?;
        let scale_z = self.read_f64()?;
        let rotation = self.read_f64()?;
        let _column_count = self.read_u16()?;
        let _row_count = self.read_u16()?;
        let _column_spacing = self.read_f64()?;
        let _row_spacing = self.read_f64()?;
        
        let mut entity = Entity::new(
            EntityType::BlockRef,
            EntityGeometry::BlockRef {
                block_name: block_name.clone(),
                position: insertion_point,
                scale_x,
                scale_y,
                scale_z,
                rotation,
                column_count: _column_count as u32,
                row_count: _row_count as u32,
                column_spacing: _column_spacing,
                row_spacing: _row_spacing,
            },
        );
        entity.set_property("block_name".to_string(), block_name);
        entity.set_property("scale_x".to_string(), scale_x.to_string());
        entity.set_property("scale_y".to_string(), scale_y.to_string());
        entity.set_property("rotation".to_string(), rotation.to_string());
        
        Ok(Some(entity))
    }

    fn parse_polyline_entity(&mut self) -> Result<Option<Entity>, DWGError> {
        let flags = self.read_u8()?;
        let _curve_type = self.read_u16()?;
        let start_width = self.read_f64()?;
        let end_width = self.read_f64()?;
        let _m_count = self.read_u16()?;
        let _n_count = self.read_u16()?;
        let _m_count_smooth = self.read_u16()?;
        let _n_count_smooth = self.read_u16()?;
        let _total_points = self.read_u32()?;
        
        let mut vertices = Vec::new();
        
        if flags & 0x08 != 0 {
            let num_vertices = self.read_u16()?;
            for _ in 0..num_vertices {
                let x = self.read_f64()?;
                let y = self.read_f64()?;
                let z = self.read_f64()?;
                vertices.push(Point::new(x, y, z));
            }
        }
        
        let polyline = Polyline::from_points(&vertices);
        Ok(Some(Entity::new(
            EntityType::Polyline,
            EntityGeometry::Polyline(polyline),
        )))
    }

    fn parse_lwpolyline_entity(&mut self) -> Result<Option<Entity>, DWGError> {
        let num_vertices = self.read_u32()?;
        let _flags = self.read_u32()?;
        let _constant_width = self.read_f64()?;
        let _elevation = self.read_f64()?;
        let _thickness = self.read_f64()?;
        let _extrusion = self.read_f64()?;
        
        let mut vertices = Vec::new();
        
        for _ in 0..num_vertices {
            let x = self.read_f64()?;
            let y = self.read_f64()?;
            let _start_width = self.read_f64()?;
            let _end_width = self.read_f64()?;
            let _bulge = self.read_f64()?;
            vertices.push(Point::new(x, y, 0.0));
        }
        
        let polyline = Polyline::from_points(&vertices);
        Ok(Some(Entity::new(
            EntityType::Polyline,
            EntityGeometry::Polyline(polyline),
        )))
    }

    fn parse_spline_entity(&mut self) -> Result<Option<Entity>, DWGError> {
        let degree = self.read_u32()?;
        let num_knots = self.read_u32()?;
        let num_control_points = self.read_u32()?;
        let _num_fit_points = self.read_u32()?;
        let _knot_tolerance = self.read_f64()?;
        let _control_point_tolerance = self.read_f64()?;
        let _fit_point_tolerance = self.read_f64()?;
        
        let mut knots = Vec::new();
        for _ in 0..num_knots {
            knots.push(self.read_f64()?);
        }
        
        let mut control_points = Vec::new();
        for _ in 0..num_control_points {
            let x = self.read_f64()?;
            let y = self.read_f64()?;
            let z = self.read_f64()?;
            control_points.push(Point::new(x, y, z));
        }
        
        let spline = BSpline::new(control_points, knots, degree as usize);
        Ok(Some(Entity::new(
            EntityType::BSpline,
            EntityGeometry::BSpline(spline),
        )))
    }

    fn parse_hatch_entity(&mut self) -> Result<Option<Entity>, DWGError> {
        let _is_associative = self.read_u32()?;
        let _boundary_paths_count = self.read_u32()?;
        let _style = self.read_u32()?;
        let _pattern_scale = self.read_f64()?;
        let _double_text_flag = self.read_u32()?;
        let _dash_distances_count = self.read_u32()?;
        let _outlier_percent = self.read_f64()?;
        let _outlier_radius = self.read_f64()?;
        let _hatch_color = self.read_u32()?;
        let _background_color = self.read_u32()?;
        let _pattern_angle = self.read_f64()?;
        let _pattern_spacing = self.read_f64()?;
        let _pattern_definition_lines = self.read_u32()?;
        
        let _fill_color = self.read_u32()?;
        
        Ok(None)
    }

    fn parse_objects_section(&mut self) -> Result<(), DWGError> {
        let section_size = self.read_u32()? as usize;
        let _section_start = self.cursor;
        self.cursor += section_size;
        Ok(())
    }

    fn parse(&mut self) -> Result<Document, DWGError> {
        self.parse_version()?;
        
        match self.version {
            DWGVersion::R12 => self.parse_r12_format()?,
            DWGVersion::R13 | DWGVersion::R14 => self.parse_r13_r14_format()?,
            _ => self.parse_modern_format()?,
        }
        
        let mut doc = Document::new(format!("DWG Document ({:?})", self.version));
        
        for (layer_name, _layer_id) in &self.layers {
            let layer = Layer::new(layer_name.clone());
            doc.add_layer(layer);
        }
        
        let mut main_block = Block::new("Model".to_string());
        for entity in &self.entities {
            main_block.add_entity(entity.clone());
        }
        doc.add_block(main_block);
        
        for block in &self.blocks {
            doc.add_block(block.clone());
        }
        
        Ok(doc)
    }

    fn parse_r12_format(&mut self) -> Result<(), DWGError> {
        let _file_maintenance = self.read_u8()?;
        let _version = self.read_u8()?;
        let _app_version = self.read_u16()?;
        let _maint_version = self.read_u8()?;
        let _drawings_unit = self.read_u8()?;
        
        self.parse_entities_section()?;
        Ok(())
    }

    fn parse_r13_r14_format(&mut self) -> Result<(), DWGError> {
        self.parse_tables_section()?;
        self.parse_blocks_section()?;
        self.parse_entities_section()?;
        Ok(())
    }

    fn parse_modern_format(&mut self) -> Result<(), DWGError> {
        let _machine_state = self.read_u32()?;
        
        self.parse_header_section()?;
        self.parse_classes_section()?;
        self.parse_tables_section()?;
        self.parse_blocks_section()?;
        self.parse_entities_section()?;
        self.parse_objects_section()?;
        Ok(())
    }
}

pub struct DWGImporter;

impl DWGImporter {
    pub fn new() -> Self {
        Self
    }

    pub fn detect_version(data: &[u8]) -> Option<DWGVersion> {
        if data.len() < 6 {
            return None;
        }
        DWGVersion::from_magic(&data[0..6])
    }
}

impl crate::io::Importer for DWGImporter {
    fn can_import(&self, extension: &str) -> bool {
        extension.to_lowercase() == "dwg"
    }

    fn import_from_file(&self, filename: &str) -> Result<Document, ImportError> {
        let mut file = std::fs::File::open(filename).map_err(|e| ImportError::Io(e.to_string()))?;
        let mut data = Vec::new();
        file.read_to_end(&mut data).map_err(|e| ImportError::Io(e.to_string()))?;
        self.import_from_bytes(&data, "dwg")
    }

    fn import_from_bytes(&self, data: &[u8], extension: &str) -> Result<Document, ImportError> {
        if !self.can_import(extension) {
            return Err(ImportError::UnsupportedFormat(extension.to_string()));
        }

        if data.len() < 6 {
            return Err(ImportError::ParseError("File too small to be a valid DWG".to_string()));
        }

        let version = DWGImporter::detect_version(data)
            .ok_or_else(|| ImportError::ParseError("Unable to detect DWG version".to_string()))?;

        let mut parser = DWGParser::new(data);
        parser.version = version;
        
        let doc = parser.parse()
            .map_err(|e| ImportError::ParseError(e.to_string()))?;
        
        Ok(doc)
    }
}

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

    #[test]
    fn test_dwg_version_detection() {
        let r12_data = b"AC1009";
        let version = DWGVersion::from_magic(r12_data);
        assert_eq!(version, Some(DWGVersion::R12));
        
        let r2000_data = b"AC1015";
        let version = DWGVersion::from_magic(r2000_data);
        assert_eq!(version, Some(DWGVersion::R2000));
        
        let r2018_data = b"AC1032";
        let version = DWGVersion::from_magic(r2018_data);
        assert_eq!(version, Some(DWGVersion::R2018));
    }

    #[test]
    fn test_dwg_importer_can_import() {
        let importer = DWGImporter::new();
        assert!(importer.can_import("dwg"));
        assert!(importer.can_import("DWG"));
        assert!(!importer.can_import("dxf"));
    }
}
