//! Code structure extraction from source files.
//!
//! Provides lightweight regex-based parsing to extract structural elements
//! like functions, structs, classes, imports, etc. from source code.

use crate::language::Language;

/// A code structure element with location information.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Symbol {
    /// The symbol name.
    pub name: String,

    /// The kind of symbol.
    pub kind: SymbolKind,

    /// Line number (1-indexed).
    pub line: usize,

    /// Column number (1-indexed).
    pub column: usize,

    /// The full signature or declaration line.
    pub signature: String,

    /// Whether this symbol is public/exported.
    pub is_public: bool,
}

/// The kind of code symbol.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum SymbolKind {
    Function,
    Method,
    Class,
    Struct,
    Enum,
    Interface,
    Trait,
    Type,
    Constant,
    Variable,
    Import,
    Module,
    Macro,
}

impl std::fmt::Display for SymbolKind {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::Function => write!(f, "function"),
            Self::Method => write!(f, "method"),
            Self::Class => write!(f, "class"),
            Self::Struct => write!(f, "struct"),
            Self::Enum => write!(f, "enum"),
            Self::Interface => write!(f, "interface"),
            Self::Trait => write!(f, "trait"),
            Self::Type => write!(f, "type"),
            Self::Constant => write!(f, "constant"),
            Self::Variable => write!(f, "variable"),
            Self::Import => write!(f, "import"),
            Self::Module => write!(f, "module"),
            Self::Macro => write!(f, "macro"),
        }
    }
}

/// Parsed code structure from a source file.
#[derive(Debug, Clone, Default)]
pub struct CodeStructure {
    /// All symbols found in the file.
    pub symbols: Vec<Symbol>,
}

impl CodeStructure {
    /// Create an empty code structure.
    pub fn new() -> Self {
        Self::default()
    }

    /// Parse code structure from content and language.
    pub fn parse(content: &str, language: Language) -> Self {
        let mut structure = Self::new();

        for (line_idx, line) in content.lines().enumerate() {
            let line_num = line_idx + 1;
            parse_line(&mut structure, line, line_num, language);
        }

        structure
    }

    /// Get all symbols of a specific kind.
    pub fn symbols_of_kind(&self, kind: SymbolKind) -> impl Iterator<Item = &Symbol> {
        self.symbols.iter().filter(move |s| s.kind == kind)
    }

    /// Get all public symbols.
    pub fn public_symbols(&self) -> impl Iterator<Item = &Symbol> {
        self.symbols.iter().filter(|s| s.is_public)
    }

    /// Get all functions (including methods).
    pub fn functions(&self) -> impl Iterator<Item = &Symbol> {
        self.symbols
            .iter()
            .filter(|s| matches!(s.kind, SymbolKind::Function | SymbolKind::Method))
    }

    /// Get all type definitions (structs, classes, enums, interfaces, traits).
    pub fn types(&self) -> impl Iterator<Item = &Symbol> {
        self.symbols.iter().filter(|s| {
            matches!(
                s.kind,
                SymbolKind::Class
                    | SymbolKind::Struct
                    | SymbolKind::Enum
                    | SymbolKind::Interface
                    | SymbolKind::Trait
                    | SymbolKind::Type
            )
        })
    }

    /// Get all imports.
    pub fn imports(&self) -> impl Iterator<Item = &Symbol> {
        self.symbols.iter().filter(|s| s.kind == SymbolKind::Import)
    }

    /// Check if the structure is empty.
    pub fn is_empty(&self) -> bool {
        self.symbols.is_empty()
    }

    /// Get the number of symbols.
    pub fn len(&self) -> usize {
        self.symbols.len()
    }
}

fn parse_line(structure: &mut CodeStructure, line: &str, line_num: usize, language: Language) {
    let trimmed = line.trim();

    // Skip empty lines and comments
    if trimmed.is_empty() || is_comment(trimmed, language) {
        return;
    }

    match language {
        Language::Rust => parse_rust_line(structure, line, trimmed, line_num),
        Language::Python => parse_python_line(structure, line, trimmed, line_num),
        Language::JavaScript | Language::Jsx => parse_js_line(structure, line, trimmed, line_num),
        Language::TypeScript | Language::Tsx => parse_ts_line(structure, line, trimmed, line_num),
        Language::Go => parse_go_line(structure, line, trimmed, line_num),
        Language::Java => parse_java_line(structure, line, trimmed, line_num),
        Language::C | Language::Cpp => parse_c_line(structure, line, trimmed, line_num),
        Language::CSharp => parse_csharp_line(structure, line, trimmed, line_num),
        Language::Ruby => parse_ruby_line(structure, line, trimmed, line_num),
        Language::Php => parse_php_line(structure, line, trimmed, line_num),
        _ => {} // Unsupported language
    }
}

fn is_comment(line: &str, language: Language) -> bool {
    match language {
        Language::Rust
        | Language::Go
        | Language::Java
        | Language::JavaScript
        | Language::TypeScript
        | Language::C
        | Language::Cpp
        | Language::CSharp
        | Language::Jsx
        | Language::Tsx
        | Language::Php => {
            line.starts_with("//") || line.starts_with("/*") || line.starts_with('*')
        }
        Language::Python | Language::Ruby => line.starts_with('#'),
        _ => false,
    }
}

fn column_of(line: &str, trimmed: &str) -> usize {
    line.find(trimmed).unwrap_or(0) + 1
}

// Rust parser
fn parse_rust_line(structure: &mut CodeStructure, line: &str, trimmed: &str, line_num: usize) {
    let is_public = trimmed.starts_with("pub ");
    let content = if is_public {
        trimmed.strip_prefix("pub ").unwrap_or(trimmed)
    } else {
        trimmed
    };

    // Handle pub(crate), pub(super), etc.
    let content = if content.starts_with('(') {
        if let Some(idx) = content.find(')') {
            content[idx + 1..].trim_start()
        } else {
            content
        }
    } else {
        content
    };

    if content.starts_with("fn ") {
        if let Some(name) = extract_identifier(content, "fn ") {
            structure.symbols.push(Symbol {
                name,
                kind: SymbolKind::Function,
                line: line_num,
                column: column_of(line, trimmed),
                signature: trimmed.to_string(),
                is_public,
            });
        }
    } else if content.starts_with("struct ") {
        if let Some(name) = extract_identifier(content, "struct ") {
            structure.symbols.push(Symbol {
                name,
                kind: SymbolKind::Struct,
                line: line_num,
                column: column_of(line, trimmed),
                signature: trimmed.to_string(),
                is_public,
            });
        }
    } else if content.starts_with("enum ") {
        if let Some(name) = extract_identifier(content, "enum ") {
            structure.symbols.push(Symbol {
                name,
                kind: SymbolKind::Enum,
                line: line_num,
                column: column_of(line, trimmed),
                signature: trimmed.to_string(),
                is_public,
            });
        }
    } else if content.starts_with("trait ") {
        if let Some(name) = extract_identifier(content, "trait ") {
            structure.symbols.push(Symbol {
                name,
                kind: SymbolKind::Trait,
                line: line_num,
                column: column_of(line, trimmed),
                signature: trimmed.to_string(),
                is_public,
            });
        }
    } else if content.starts_with("type ") {
        if let Some(name) = extract_identifier(content, "type ") {
            structure.symbols.push(Symbol {
                name,
                kind: SymbolKind::Type,
                line: line_num,
                column: column_of(line, trimmed),
                signature: trimmed.to_string(),
                is_public,
            });
        }
    } else if content.starts_with("const ") {
        if let Some(name) = extract_identifier(content, "const ") {
            structure.symbols.push(Symbol {
                name,
                kind: SymbolKind::Constant,
                line: line_num,
                column: column_of(line, trimmed),
                signature: trimmed.to_string(),
                is_public,
            });
        }
    } else if content.starts_with("static ") {
        if let Some(name) = extract_identifier(content, "static ") {
            structure.symbols.push(Symbol {
                name,
                kind: SymbolKind::Variable,
                line: line_num,
                column: column_of(line, trimmed),
                signature: trimmed.to_string(),
                is_public,
            });
        }
    } else if content.starts_with("mod ") {
        if let Some(name) = extract_identifier(content, "mod ") {
            structure.symbols.push(Symbol {
                name,
                kind: SymbolKind::Module,
                line: line_num,
                column: column_of(line, trimmed),
                signature: trimmed.to_string(),
                is_public,
            });
        }
    } else if content.starts_with("macro_rules! ") {
        if let Some(name) = extract_identifier(content, "macro_rules! ") {
            structure.symbols.push(Symbol {
                name,
                kind: SymbolKind::Macro,
                line: line_num,
                column: column_of(line, trimmed),
                signature: trimmed.to_string(),
                is_public,
            });
        }
    } else if trimmed.starts_with("use ") {
        let import = trimmed
            .strip_prefix("use ")
            .unwrap_or("")
            .trim_end_matches(';')
            .to_string();
        structure.symbols.push(Symbol {
            name: import.clone(),
            kind: SymbolKind::Import,
            line: line_num,
            column: column_of(line, trimmed),
            signature: trimmed.to_string(),
            is_public: false,
        });
    }
}

// Python parser
fn parse_python_line(structure: &mut CodeStructure, line: &str, trimmed: &str, line_num: usize) {
    if trimmed.starts_with("def ") {
        if let Some(name) = extract_until(trimmed, "def ", '(') {
            structure.symbols.push(Symbol {
                name,
                kind: SymbolKind::Function,
                line: line_num,
                column: column_of(line, trimmed),
                signature: trimmed.trim_end_matches(':').to_string(),
                is_public: !trimmed.contains("def _"),
            });
        }
    } else if trimmed.starts_with("async def ") {
        if let Some(name) = extract_until(trimmed, "async def ", '(') {
            structure.symbols.push(Symbol {
                name,
                kind: SymbolKind::Function,
                line: line_num,
                column: column_of(line, trimmed),
                signature: trimmed.trim_end_matches(':').to_string(),
                is_public: !trimmed.contains("def _"),
            });
        }
    } else if trimmed.starts_with("class ") {
        if let Some(name) = extract_until_any(trimmed, "class ", &['(', ':']) {
            structure.symbols.push(Symbol {
                name,
                kind: SymbolKind::Class,
                line: line_num,
                column: column_of(line, trimmed),
                signature: trimmed.trim_end_matches(':').to_string(),
                is_public: !trimmed.contains("class _"),
            });
        }
    } else if trimmed.starts_with("import ") || trimmed.starts_with("from ") {
        structure.symbols.push(Symbol {
            name: trimmed.to_string(),
            kind: SymbolKind::Import,
            line: line_num,
            column: column_of(line, trimmed),
            signature: trimmed.to_string(),
            is_public: false,
        });
    }
}

// JavaScript parser
fn parse_js_line(structure: &mut CodeStructure, line: &str, trimmed: &str, line_num: usize) {
    let is_export = trimmed.starts_with("export ");
    let content = if is_export {
        trimmed.strip_prefix("export ").unwrap_or(trimmed)
    } else {
        trimmed
    };
    let content = content.strip_prefix("default ").unwrap_or(content);

    if content.starts_with("function ") || content.starts_with("async function ") {
        let prefix = if content.starts_with("async ") {
            "async function "
        } else {
            "function "
        };
        if let Some(name) = extract_until(content, prefix, '(') {
            structure.symbols.push(Symbol {
                name,
                kind: SymbolKind::Function,
                line: line_num,
                column: column_of(line, trimmed),
                signature: trimmed.to_string(),
                is_public: is_export,
            });
        }
    } else if content.starts_with("class ") {
        if let Some(name) = extract_until_any(content, "class ", &[' ', '{']) {
            structure.symbols.push(Symbol {
                name,
                kind: SymbolKind::Class,
                line: line_num,
                column: column_of(line, trimmed),
                signature: trimmed.to_string(),
                is_public: is_export,
            });
        }
    } else if content.starts_with("const ")
        || content.starts_with("let ")
        || content.starts_with("var ")
    {
        let prefix = if content.starts_with("const ") {
            "const "
        } else if content.starts_with("let ") {
            "let "
        } else {
            "var "
        };
        if let Some(name) = extract_until_any(content, prefix, &[' ', '=', ':']) {
            // Check if it's an arrow function
            let kind = if content.contains("=>") || content.contains("function") {
                SymbolKind::Function
            } else if prefix == "const " {
                SymbolKind::Constant
            } else {
                SymbolKind::Variable
            };
            structure.symbols.push(Symbol {
                name,
                kind,
                line: line_num,
                column: column_of(line, trimmed),
                signature: trimmed.to_string(),
                is_public: is_export,
            });
        }
    } else if trimmed.starts_with("import ") {
        structure.symbols.push(Symbol {
            name: trimmed.to_string(),
            kind: SymbolKind::Import,
            line: line_num,
            column: column_of(line, trimmed),
            signature: trimmed.to_string(),
            is_public: false,
        });
    }
}

// TypeScript parser (extends JS)
fn parse_ts_line(structure: &mut CodeStructure, line: &str, trimmed: &str, line_num: usize) {
    let is_export = trimmed.starts_with("export ");
    let content = if is_export {
        trimmed.strip_prefix("export ").unwrap_or(trimmed)
    } else {
        trimmed
    };

    if content.starts_with("interface ") {
        if let Some(name) = extract_until_any(content, "interface ", &[' ', '<', '{']) {
            structure.symbols.push(Symbol {
                name,
                kind: SymbolKind::Interface,
                line: line_num,
                column: column_of(line, trimmed),
                signature: trimmed.to_string(),
                is_public: is_export,
            });
            return;
        }
    } else if content.starts_with("type ") {
        if let Some(name) = extract_until_any(content, "type ", &[' ', '<', '=']) {
            structure.symbols.push(Symbol {
                name,
                kind: SymbolKind::Type,
                line: line_num,
                column: column_of(line, trimmed),
                signature: trimmed.to_string(),
                is_public: is_export,
            });
            return;
        }
    } else if content.starts_with("enum ") {
        if let Some(name) = extract_until_any(content, "enum ", &[' ', '{']) {
            structure.symbols.push(Symbol {
                name,
                kind: SymbolKind::Enum,
                line: line_num,
                column: column_of(line, trimmed),
                signature: trimmed.to_string(),
                is_public: is_export,
            });
            return;
        }
    }

    // Fall back to JS parsing
    parse_js_line(structure, line, trimmed, line_num);
}

// Go parser
fn parse_go_line(structure: &mut CodeStructure, line: &str, trimmed: &str, line_num: usize) {
    if trimmed.starts_with("func ") {
        // Check if it's a method (has receiver)
        let is_method = trimmed.starts_with("func (");
        if is_method {
            // Method: func (r Receiver) Name(...)
            if let Some(paren_end) = trimmed.find(") ") {
                let after_receiver = &trimmed[paren_end + 2..];
                if let Some(name) = extract_until(after_receiver, "", '(') {
                    let is_public = name
                        .chars()
                        .next()
                        .map(|c| c.is_uppercase())
                        .unwrap_or(false);
                    structure.symbols.push(Symbol {
                        name,
                        kind: SymbolKind::Method,
                        line: line_num,
                        column: column_of(line, trimmed),
                        signature: trimmed.to_string(),
                        is_public,
                    });
                }
            }
        } else if let Some(name) = extract_until(trimmed, "func ", '(') {
            let is_public = name
                .chars()
                .next()
                .map(|c| c.is_uppercase())
                .unwrap_or(false);
            structure.symbols.push(Symbol {
                name,
                kind: SymbolKind::Function,
                line: line_num,
                column: column_of(line, trimmed),
                signature: trimmed.to_string(),
                is_public,
            });
        }
    } else if trimmed.starts_with("type ") {
        if let Some(rest) = trimmed.strip_prefix("type ") {
            let parts: Vec<&str> = rest.split_whitespace().collect();
            if parts.len() >= 2 {
                let name = parts[0].to_string();
                let is_public = name
                    .chars()
                    .next()
                    .map(|c| c.is_uppercase())
                    .unwrap_or(false);
                let kind = match parts[1] {
                    "struct" => SymbolKind::Struct,
                    "interface" => SymbolKind::Interface,
                    _ => SymbolKind::Type,
                };
                structure.symbols.push(Symbol {
                    name,
                    kind,
                    line: line_num,
                    column: column_of(line, trimmed),
                    signature: trimmed.to_string(),
                    is_public,
                });
            }
        }
    } else if trimmed.starts_with("const ") {
        if let Some(name) = extract_until_any(trimmed, "const ", &[' ', '=']) {
            let is_public = name
                .chars()
                .next()
                .map(|c| c.is_uppercase())
                .unwrap_or(false);
            structure.symbols.push(Symbol {
                name,
                kind: SymbolKind::Constant,
                line: line_num,
                column: column_of(line, trimmed),
                signature: trimmed.to_string(),
                is_public,
            });
        }
    } else if trimmed.starts_with("var ") {
        if let Some(name) = extract_until_any(trimmed, "var ", &[' ', '=']) {
            let is_public = name
                .chars()
                .next()
                .map(|c| c.is_uppercase())
                .unwrap_or(false);
            structure.symbols.push(Symbol {
                name,
                kind: SymbolKind::Variable,
                line: line_num,
                column: column_of(line, trimmed),
                signature: trimmed.to_string(),
                is_public,
            });
        }
    } else if trimmed.starts_with("import ") || trimmed.starts_with("import (") {
        structure.symbols.push(Symbol {
            name: trimmed.to_string(),
            kind: SymbolKind::Import,
            line: line_num,
            column: column_of(line, trimmed),
            signature: trimmed.to_string(),
            is_public: false,
        });
    }
}

// Java parser
fn parse_java_line(structure: &mut CodeStructure, line: &str, trimmed: &str, line_num: usize) {
    let is_public = trimmed.contains("public ");

    if (trimmed.contains("class ") || trimmed.contains("interface ") || trimmed.contains("enum "))
        && !trimmed.starts_with("//")
    {
        let kind = if trimmed.contains("interface ") {
            SymbolKind::Interface
        } else if trimmed.contains("enum ") {
            SymbolKind::Enum
        } else {
            SymbolKind::Class
        };

        let keyword = match kind {
            SymbolKind::Interface => "interface ",
            SymbolKind::Enum => "enum ",
            _ => "class ",
        };

        if let Some(idx) = trimmed.find(keyword) {
            let after = &trimmed[idx + keyword.len()..];
            if let Some(name) = extract_until_any(after, "", &[' ', '<', '{']) {
                structure.symbols.push(Symbol {
                    name,
                    kind,
                    line: line_num,
                    column: column_of(line, trimmed),
                    signature: trimmed.to_string(),
                    is_public,
                });
            }
        }
    } else if (trimmed.contains('(')
        && trimmed.contains(')')
        && !trimmed.contains("if ")
        && !trimmed.contains("while ")
        && !trimmed.contains("for ")
        && !trimmed.contains("switch "))
        && (trimmed.contains("void ")
            || trimmed.contains("int ")
            || trimmed.contains("String ")
            || trimmed.contains("boolean ")
            || trimmed.contains("Object ")
            || trimmed.contains("> "))
    {
        // Likely a method
        if let Some(paren_idx) = trimmed.find('(') {
            let before_paren = &trimmed[..paren_idx];
            let parts: Vec<&str> = before_paren.split_whitespace().collect();
            if let Some(name) = parts.last() {
                structure.symbols.push(Symbol {
                    name: name.to_string(),
                    kind: SymbolKind::Method,
                    line: line_num,
                    column: column_of(line, trimmed),
                    signature: trimmed.to_string(),
                    is_public,
                });
            }
        }
    } else if trimmed.starts_with("import ") {
        structure.symbols.push(Symbol {
            name: trimmed
                .strip_prefix("import ")
                .unwrap_or("")
                .trim_end_matches(';')
                .to_string(),
            kind: SymbolKind::Import,
            line: line_num,
            column: column_of(line, trimmed),
            signature: trimmed.to_string(),
            is_public: false,
        });
    }
}

// C/C++ parser
fn parse_c_line(structure: &mut CodeStructure, line: &str, trimmed: &str, line_num: usize) {
    if trimmed.starts_with("struct ") {
        if let Some(name) = extract_until_any(trimmed, "struct ", &[' ', '{', ';']) {
            structure.symbols.push(Symbol {
                name,
                kind: SymbolKind::Struct,
                line: line_num,
                column: column_of(line, trimmed),
                signature: trimmed.to_string(),
                is_public: true,
            });
        }
    } else if trimmed.starts_with("enum ") {
        if let Some(name) = extract_until_any(trimmed, "enum ", &[' ', '{', ';']) {
            structure.symbols.push(Symbol {
                name,
                kind: SymbolKind::Enum,
                line: line_num,
                column: column_of(line, trimmed),
                signature: trimmed.to_string(),
                is_public: true,
            });
        }
    } else if trimmed.starts_with("class ") {
        if let Some(name) = extract_until_any(trimmed, "class ", &[' ', '{', ':']) {
            structure.symbols.push(Symbol {
                name,
                kind: SymbolKind::Class,
                line: line_num,
                column: column_of(line, trimmed),
                signature: trimmed.to_string(),
                is_public: true,
            });
        }
    } else if trimmed.starts_with("#define ") {
        if let Some(name) = extract_until_any(trimmed, "#define ", &[' ', '(']) {
            structure.symbols.push(Symbol {
                name,
                kind: SymbolKind::Macro,
                line: line_num,
                column: column_of(line, trimmed),
                signature: trimmed.to_string(),
                is_public: true,
            });
        }
    } else if trimmed.starts_with("#include ") {
        structure.symbols.push(Symbol {
            name: trimmed.strip_prefix("#include ").unwrap_or("").to_string(),
            kind: SymbolKind::Import,
            line: line_num,
            column: column_of(line, trimmed),
            signature: trimmed.to_string(),
            is_public: false,
        });
    } else if trimmed.starts_with("typedef ") {
        // typedef ... name;
        if let Some(semicolon_idx) = trimmed.rfind(';') {
            let before = &trimmed[..semicolon_idx];
            let parts: Vec<&str> = before.split_whitespace().collect();
            if let Some(name) = parts.last() {
                structure.symbols.push(Symbol {
                    name: name.to_string(),
                    kind: SymbolKind::Type,
                    line: line_num,
                    column: column_of(line, trimmed),
                    signature: trimmed.to_string(),
                    is_public: true,
                });
            }
        }
    } else if trimmed.contains('(')
        && !trimmed.starts_with("if ")
        && !trimmed.starts_with("while ")
        && !trimmed.starts_with("for ")
        && !trimmed.starts_with("switch ")
        && !trimmed.starts_with("#")
    {
        // Possibly a function definition
        if let Some(paren_idx) = trimmed.find('(') {
            let before_paren = &trimmed[..paren_idx];
            let parts: Vec<&str> = before_paren.split_whitespace().collect();
            if parts.len() >= 2 {
                if let Some(name) = parts.last() {
                    // Filter out control flow and common non-function patterns
                    if !["if", "while", "for", "switch", "return", "sizeof"].contains(name) {
                        structure.symbols.push(Symbol {
                            name: name.trim_start_matches('*').to_string(),
                            kind: SymbolKind::Function,
                            line: line_num,
                            column: column_of(line, trimmed),
                            signature: trimmed.to_string(),
                            is_public: true,
                        });
                    }
                }
            }
        }
    }
}

// C# parser
fn parse_csharp_line(structure: &mut CodeStructure, line: &str, trimmed: &str, line_num: usize) {
    let is_public = trimmed.contains("public ");

    if trimmed.contains("class ") && !trimmed.starts_with("//") {
        if let Some(idx) = trimmed.find("class ") {
            let after = &trimmed[idx + 6..];
            if let Some(name) = extract_until_any(after, "", &[' ', '<', '{', ':']) {
                structure.symbols.push(Symbol {
                    name,
                    kind: SymbolKind::Class,
                    line: line_num,
                    column: column_of(line, trimmed),
                    signature: trimmed.to_string(),
                    is_public,
                });
            }
        }
    } else if trimmed.contains("interface ") && !trimmed.starts_with("//") {
        if let Some(idx) = trimmed.find("interface ") {
            let after = &trimmed[idx + 10..];
            if let Some(name) = extract_until_any(after, "", &[' ', '<', '{', ':']) {
                structure.symbols.push(Symbol {
                    name,
                    kind: SymbolKind::Interface,
                    line: line_num,
                    column: column_of(line, trimmed),
                    signature: trimmed.to_string(),
                    is_public,
                });
            }
        }
    } else if trimmed.contains("struct ") && !trimmed.starts_with("//") {
        if let Some(idx) = trimmed.find("struct ") {
            let after = &trimmed[idx + 7..];
            if let Some(name) = extract_until_any(after, "", &[' ', '<', '{']) {
                structure.symbols.push(Symbol {
                    name,
                    kind: SymbolKind::Struct,
                    line: line_num,
                    column: column_of(line, trimmed),
                    signature: trimmed.to_string(),
                    is_public,
                });
            }
        }
    } else if trimmed.contains("enum ") && !trimmed.starts_with("//") {
        if let Some(idx) = trimmed.find("enum ") {
            let after = &trimmed[idx + 5..];
            if let Some(name) = extract_until_any(after, "", &[' ', '{']) {
                structure.symbols.push(Symbol {
                    name,
                    kind: SymbolKind::Enum,
                    line: line_num,
                    column: column_of(line, trimmed),
                    signature: trimmed.to_string(),
                    is_public,
                });
            }
        }
    } else if trimmed.starts_with("using ") && !trimmed.contains('(') {
        structure.symbols.push(Symbol {
            name: trimmed
                .strip_prefix("using ")
                .unwrap_or("")
                .trim_end_matches(';')
                .to_string(),
            kind: SymbolKind::Import,
            line: line_num,
            column: column_of(line, trimmed),
            signature: trimmed.to_string(),
            is_public: false,
        });
    }
}

// Ruby parser
fn parse_ruby_line(structure: &mut CodeStructure, line: &str, trimmed: &str, line_num: usize) {
    if trimmed.starts_with("def ") {
        if let Some(name) = extract_until_any(trimmed, "def ", &['(', '\n', ' ']) {
            structure.symbols.push(Symbol {
                name: name.clone(),
                kind: SymbolKind::Function,
                line: line_num,
                column: column_of(line, trimmed),
                signature: trimmed.to_string(),
                is_public: !name.starts_with('_'),
            });
        }
    } else if trimmed.starts_with("class ") {
        if let Some(name) = extract_until_any(trimmed, "class ", &[' ', '<', '\n']) {
            structure.symbols.push(Symbol {
                name,
                kind: SymbolKind::Class,
                line: line_num,
                column: column_of(line, trimmed),
                signature: trimmed.to_string(),
                is_public: true,
            });
        }
    } else if trimmed.starts_with("module ") {
        if let Some(name) = extract_until_any(trimmed, "module ", &[' ', '\n']) {
            structure.symbols.push(Symbol {
                name,
                kind: SymbolKind::Module,
                line: line_num,
                column: column_of(line, trimmed),
                signature: trimmed.to_string(),
                is_public: true,
            });
        }
    } else if trimmed.starts_with("require ") || trimmed.starts_with("require_relative ") {
        structure.symbols.push(Symbol {
            name: trimmed.to_string(),
            kind: SymbolKind::Import,
            line: line_num,
            column: column_of(line, trimmed),
            signature: trimmed.to_string(),
            is_public: false,
        });
    }
}

// PHP parser
fn parse_php_line(structure: &mut CodeStructure, line: &str, trimmed: &str, line_num: usize) {
    let is_public = trimmed.contains("public ");

    if trimmed.contains("function ") {
        if let Some(idx) = trimmed.find("function ") {
            let after = &trimmed[idx + 9..];
            if let Some(name) = extract_until(after, "", '(') {
                structure.symbols.push(Symbol {
                    name,
                    kind: SymbolKind::Function,
                    line: line_num,
                    column: column_of(line, trimmed),
                    signature: trimmed.to_string(),
                    is_public,
                });
            }
        }
    } else if trimmed.contains("class ") && !trimmed.starts_with("//") {
        if let Some(idx) = trimmed.find("class ") {
            let after = &trimmed[idx + 6..];
            if let Some(name) = extract_until_any(after, "", &[' ', '{']) {
                structure.symbols.push(Symbol {
                    name,
                    kind: SymbolKind::Class,
                    line: line_num,
                    column: column_of(line, trimmed),
                    signature: trimmed.to_string(),
                    is_public,
                });
            }
        }
    } else if trimmed.contains("interface ") && !trimmed.starts_with("//") {
        if let Some(idx) = trimmed.find("interface ") {
            let after = &trimmed[idx + 10..];
            if let Some(name) = extract_until_any(after, "", &[' ', '{']) {
                structure.symbols.push(Symbol {
                    name,
                    kind: SymbolKind::Interface,
                    line: line_num,
                    column: column_of(line, trimmed),
                    signature: trimmed.to_string(),
                    is_public,
                });
            }
        }
    } else if trimmed.contains("trait ") && !trimmed.starts_with("//") {
        if let Some(idx) = trimmed.find("trait ") {
            let after = &trimmed[idx + 6..];
            if let Some(name) = extract_until_any(after, "", &[' ', '{']) {
                structure.symbols.push(Symbol {
                    name,
                    kind: SymbolKind::Trait,
                    line: line_num,
                    column: column_of(line, trimmed),
                    signature: trimmed.to_string(),
                    is_public,
                });
            }
        }
    } else if trimmed.starts_with("use ") {
        structure.symbols.push(Symbol {
            name: trimmed
                .strip_prefix("use ")
                .unwrap_or("")
                .trim_end_matches(';')
                .to_string(),
            kind: SymbolKind::Import,
            line: line_num,
            column: column_of(line, trimmed),
            signature: trimmed.to_string(),
            is_public: false,
        });
    }
}

// Helper functions
fn extract_identifier(line: &str, prefix: &str) -> Option<String> {
    let rest = line.strip_prefix(prefix)?;
    let end = rest.find(|c: char| !c.is_alphanumeric() && c != '_')?;
    let name = rest[..end].to_string();
    if name.is_empty() { None } else { Some(name) }
}

fn extract_until(line: &str, prefix: &str, delimiter: char) -> Option<String> {
    let rest = if prefix.is_empty() {
        line
    } else {
        line.strip_prefix(prefix)?
    };
    let end = rest.find(delimiter).unwrap_or(rest.len());
    let name = rest[..end].trim().to_string();
    if name.is_empty() { None } else { Some(name) }
}

fn extract_until_any(line: &str, prefix: &str, delimiters: &[char]) -> Option<String> {
    let rest = if prefix.is_empty() {
        line
    } else {
        line.strip_prefix(prefix)?
    };
    let end = rest
        .find(|c: char| delimiters.contains(&c))
        .unwrap_or(rest.len());
    let name = rest[..end].trim().to_string();
    if name.is_empty() { None } else { Some(name) }
}

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

    #[test]
    fn test_rust_parsing() {
        let code = r#"
use std::path::Path;

pub fn hello_world() {
    println!("Hello");
}

pub struct MyStruct {
    field: i32,
}

enum Status {
    Active,
    Inactive,
}

pub trait MyTrait {
    fn do_something(&self);
}
"#;
        let structure = CodeStructure::parse(code, Language::Rust);

        assert!(
            structure
                .symbols
                .iter()
                .any(|s| s.name == "std::path::Path" && s.kind == SymbolKind::Import)
        );
        assert!(
            structure
                .symbols
                .iter()
                .any(|s| s.name == "hello_world" && s.kind == SymbolKind::Function && s.is_public)
        );
        assert!(
            structure
                .symbols
                .iter()
                .any(|s| s.name == "MyStruct" && s.kind == SymbolKind::Struct && s.is_public)
        );
        assert!(
            structure
                .symbols
                .iter()
                .any(|s| s.name == "Status" && s.kind == SymbolKind::Enum && !s.is_public)
        );
        assert!(
            structure
                .symbols
                .iter()
                .any(|s| s.name == "MyTrait" && s.kind == SymbolKind::Trait && s.is_public)
        );
    }

    #[test]
    fn test_python_parsing() {
        let code = r#"
import os
from pathlib import Path

def hello():
    pass

class MyClass:
    def __init__(self):
        pass

async def fetch_data():
    pass
"#;
        let structure = CodeStructure::parse(code, Language::Python);

        assert!(
            structure
                .symbols
                .iter()
                .any(|s| s.kind == SymbolKind::Import)
        );
        assert!(
            structure
                .symbols
                .iter()
                .any(|s| s.name == "hello" && s.kind == SymbolKind::Function)
        );
        assert!(
            structure
                .symbols
                .iter()
                .any(|s| s.name == "MyClass" && s.kind == SymbolKind::Class)
        );
        assert!(
            structure
                .symbols
                .iter()
                .any(|s| s.name == "fetch_data" && s.kind == SymbolKind::Function)
        );
    }

    #[test]
    fn test_typescript_parsing() {
        let code = r#"
import { Component } from 'react';

export interface User {
    name: string;
}

export type Status = 'active' | 'inactive';

export class UserService {
    getUser() {}
}

export const API_URL = 'https://api.example.com';

export function fetchUser(id: number) {}
"#;
        let structure = CodeStructure::parse(code, Language::TypeScript);

        assert!(
            structure
                .symbols
                .iter()
                .any(|s| s.kind == SymbolKind::Import)
        );
        assert!(
            structure
                .symbols
                .iter()
                .any(|s| s.name == "User" && s.kind == SymbolKind::Interface && s.is_public)
        );
        assert!(
            structure
                .symbols
                .iter()
                .any(|s| s.name == "Status" && s.kind == SymbolKind::Type && s.is_public)
        );
        assert!(
            structure
                .symbols
                .iter()
                .any(|s| s.name == "UserService" && s.kind == SymbolKind::Class && s.is_public)
        );
        assert!(
            structure
                .symbols
                .iter()
                .any(|s| s.name == "fetchUser" && s.kind == SymbolKind::Function && s.is_public)
        );
    }

    #[test]
    fn test_go_parsing() {
        let code = r#"
package main

import "fmt"

func main() {
    fmt.Println("Hello")
}

type User struct {
    Name string
}

func (u *User) GetName() string {
    return u.Name
}

const MaxSize = 100
"#;
        let structure = CodeStructure::parse(code, Language::Go);

        assert!(
            structure
                .symbols
                .iter()
                .any(|s| s.kind == SymbolKind::Import)
        );
        assert!(
            structure
                .symbols
                .iter()
                .any(|s| s.name == "main" && s.kind == SymbolKind::Function)
        );
        assert!(
            structure
                .symbols
                .iter()
                .any(|s| s.name == "User" && s.kind == SymbolKind::Struct && s.is_public)
        );
        assert!(
            structure
                .symbols
                .iter()
                .any(|s| s.name == "GetName" && s.kind == SymbolKind::Method && s.is_public)
        );
        assert!(
            structure
                .symbols
                .iter()
                .any(|s| s.name == "MaxSize" && s.kind == SymbolKind::Constant && s.is_public)
        );
    }
}
