//! Code formatting for Ruchy

use crate::backend::transpiler::Transpiler;
use crate::frontend::parser::Parser;
use tower_lsp::jsonrpc::Result;

pub struct Formatter {
    _transpiler: Transpiler,
}

impl Formatter {
    pub fn new() -> Self {
        Self {
            _transpiler: Transpiler::new(),
        }
    }

    /// Format Ruchy code
    ///
    /// # Errors
    ///
    /// This function currently does not return errors but returns Result for future compatibility
    pub fn format(&self, document: &str) -> Result<String> {
        // For now, basic formatting - in the future this would be more sophisticated
        let formatted = Self::basic_format(document);

        // Validate the formatted code still parses
        let mut parser = Parser::new(&formatted);
        if parser.parse().is_err() {
            // If formatting broke the code, return original
            return Ok(document.to_string());
        }

        Ok(formatted)
    }

    fn basic_format(document: &str) -> String {
        let lines: Vec<&str> = document.lines().collect();
        let mut formatted_lines = Vec::new();
        let mut indent_level: usize = 0;

        for line in lines {
            let trimmed = line.trim();

            // Skip empty lines
            if trimmed.is_empty() {
                formatted_lines.push(String::new());
                continue;
            }

            // Adjust indent level based on content
            let mut current_indent = indent_level;

            // Decrease indent for closing braces
            if trimmed.starts_with('}') || trimmed == "}" {
                current_indent = current_indent.saturating_sub(1);
                indent_level = current_indent;
            }

            // Add indentation
            let indented_line = format!("{}{}", "    ".repeat(current_indent), trimmed);
            formatted_lines.push(indented_line);

            // Increase indent for opening braces
            if trimmed.ends_with('{') {
                indent_level += 1;
            }
        }

        formatted_lines.join("\n")
    }
}

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

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

    #[test]
    fn test_basic_formatting() -> anyhow::Result<()> {
        let formatter = Formatter::new();
        let input = "fun test() {\nlet x = 1\nif true {\nprint(x)\n}\n}";
        let result = formatter.format(input)?;

        assert!(result.contains("    let x = 1"));
        assert!(result.contains("        print(x)"));
        Ok(())
    }

    #[test]
    fn test_empty_lines_preserved() -> anyhow::Result<()> {
        let formatter = Formatter::new();
        let input = "fun test() {\n\nlet x = 1\n\n}";
        let result = formatter.format(input)?;

        assert!(result.contains("\n\n"));
        Ok(())
    }
}
