use crate::Unparser;
use pretty_assertions::assert_eq;
use rustpython_ast as ast;
use rustpython_ast::Stmt;

/// Helper to create a StmtExpr with a string constant
fn create_comment_stmt(comment: &str) -> Stmt {
    let comment_expr = ast::ExprConstant {
        value: ast::Constant::Str(comment.to_string()),
        kind: None,
        range: Default::default(),
    };

    Stmt::Expr(ast::StmtExpr {
        value: Box::new(ast::Expr::Constant(comment_expr)),
        range: Default::default(),
    })
}

#[test]
fn test_comment_unparsing() {
    // Create various comment types
    let test_cases = [
        // Regular comment
        ("# This is a comment", "# This is a comment"),
        // Empty line
        ("", ""),
        // Shebang
        ("#!/usr/bin/env python3", "#!/usr/bin/env python3"),
        // Module headers - these don't need the # prefix since our handler adds it
        ("─ Module: test_module ─", "# ─ Module: test_module ─"),
        ("─ Entry Module: main ─", "# ─ Entry Module: main ─"),
        ("Preserved imports", "# Preserved imports"),
    ];

    for (input, expected) in test_cases {
        // Create a comment statement
        let stmt = create_comment_stmt(input);

        // Unparse it
        let mut unparser = Unparser::new();
        unparser.unparse_stmt(&stmt);

        // Verify output
        let result = unparser.source.trim();
        assert_eq!(
            result, expected,
            "Comment '{}' unparsed incorrectly as '{}'",
            input, result
        );
    }
}

#[test]
fn test_mixed_content_unparsing() {
    // Create a module with mixed content including comments
    let module_stmts = vec![
        create_comment_stmt("#!/usr/bin/env python3"),
        create_comment_stmt("# Generated by Serpen"),
        create_comment_stmt(""),
        // A regular Python import
        Stmt::Import(ast::StmtImport {
            names: vec![ast::Alias {
                name: "sys".into(),
                asname: None,
                range: Default::default(),
            }],
            range: Default::default(),
        }),
        create_comment_stmt(""),
        create_comment_stmt("# ─ Module: my_module ─"),
        // A Python function
        Stmt::FunctionDef(ast::StmtFunctionDef {
            name: "hello".into(),
            args: Box::new(ast::Arguments {
                posonlyargs: vec![],
                args: vec![],
                vararg: None,
                kwonlyargs: vec![],
                kwarg: None,
                range: Default::default(),
            }),
            body: vec![Stmt::Expr(ast::StmtExpr {
                value: Box::new(ast::Expr::Call(ast::ExprCall {
                    func: Box::new(ast::Expr::Name(ast::ExprName {
                        id: "print".into(),
                        ctx: ast::ExprContext::Load,
                        range: Default::default(),
                    })),
                    args: vec![ast::Expr::Constant(ast::ExprConstant {
                        value: ast::Constant::Str("Hello, World!".to_string()),
                        kind: None,
                        range: Default::default(),
                    })],
                    keywords: vec![],
                    range: Default::default(),
                })),
                range: Default::default(),
            })],
            decorator_list: vec![],
            returns: None,
            type_comment: None,
            type_params: Vec::new(),
            range: Default::default(),
        }),
    ];

    // Unparse the whole module
    let mut unparser = Unparser::new();
    for stmt in &module_stmts {
        unparser.unparse_stmt(stmt);
    }

    // Verify the output structure
    let expected = r#"#!/usr/bin/env python3

# Generated by Serpen

import sys

# ─ Module: my_module ─
def hello():
    print('Hello, World!')"#;

    assert_eq!(unparser.source.trim(), expected);
}
