//! Parser for the Lux language

#![allow(dead_code)]

use crate::ast::*;
use crate::diagnostics::{Diagnostic, ErrorCode, Severity};
use crate::lexer::{LexError, Lexer, StringPart, Token, TokenKind};
use std::fmt;

/// Parser error
#[derive(Debug, Clone)]
pub struct ParseError {
    pub message: String,
    pub span: Span,
}

impl fmt::Display for ParseError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(
            f,
            "Parse error at {}-{}: {}",
            self.span.start, self.span.end, self.message
        )
    }
}

impl ParseError {
    /// Convert to a rich diagnostic for Elm-style error display
    pub fn to_diagnostic(&self) -> Diagnostic {
        let (code, title, hints) = categorize_parse_error(&self.message);

        Diagnostic {
            severity: Severity::Error,
            code,
            title,
            message: self.message.clone(),
            span: self.span,
            hints,
            expected_type: None,
            actual_type: None,
            secondary_spans: Vec::new(),
        }
    }
}

/// Categorize parse errors to provide better titles, hints, and error codes
fn categorize_parse_error(message: &str) -> (Option<ErrorCode>, String, Vec<String>) {
    let message_lower = message.to_lowercase();

    if message_lower.contains("unexpected") && message_lower.contains("expected") {
        (
            Some(ErrorCode::E0101),
            "Unexpected Token".to_string(),
            vec!["Check for missing or misplaced punctuation.".to_string()],
        )
    } else if message_lower.contains("expected") && message_lower.contains("expression") {
        (
            Some(ErrorCode::E0101),
            "Missing Expression".to_string(),
            vec!["An expression was expected here.".to_string()],
        )
    } else if message_lower.contains("expected") && message_lower.contains(":") {
        (
            Some(ErrorCode::E0104),
            "Missing Type Annotation".to_string(),
            vec!["A type annotation is required here.".to_string()],
        )
    } else if message_lower.contains("unclosed") || message_lower.contains("unterminated") {
        (
            Some(ErrorCode::E0102),
            "Unclosed Delimiter".to_string(),
            vec![
                "Check for matching opening and closing brackets.".to_string(),
                "Make sure all strings are properly closed with quotes.".to_string(),
            ],
        )
    } else if message_lower.contains("invalid") && message_lower.contains("literal") {
        (
            Some(ErrorCode::E0103),
            "Invalid Literal".to_string(),
            vec!["Check the format of the literal value.".to_string()],
        )
    } else if message_lower.contains("invalid") && message_lower.contains("operator") {
        (
            Some(ErrorCode::E0105),
            "Invalid Operator".to_string(),
            vec!["Check the operator syntax.".to_string()],
        )
    } else if message_lower.contains("invalid") {
        (
            Some(ErrorCode::E0100),
            "Invalid Syntax".to_string(),
            vec!["Check the syntax of this construct.".to_string()],
        )
    } else if message_lower.contains("identifier") {
        (
            Some(ErrorCode::E0100),
            "Invalid Identifier".to_string(),
            vec!["Identifiers must start with a letter and contain only letters, numbers, and underscores.".to_string()],
        )
    } else {
        (Some(ErrorCode::E0100), "Parse Error".to_string(), vec![])
    }
}

impl From<LexError> for ParseError {
    fn from(err: LexError) -> Self {
        ParseError {
            message: err.message,
            span: err.span,
        }
    }
}

/// The parser
pub struct Parser {
    tokens: Vec<Token>,
    pos: usize,
    eof_token: Token,
}

impl Parser {
    pub fn new(tokens: Vec<Token>) -> Self {
        Self {
            tokens,
            pos: 0,
            eof_token: Token::new(TokenKind::Eof, Span::default()),
        }
    }

    pub fn parse_source(source: &str) -> Result<Program, ParseError> {
        let tokens = Lexer::new(source).tokenize()?;
        let mut parser = Parser::new(tokens);
        parser.parse_program()
    }

    /// Parse a complete program
    pub fn parse_program(&mut self) -> Result<Program, ParseError> {
        let mut imports = Vec::new();
        let mut declarations = Vec::new();
        self.skip_newlines();

        // Parse imports first (they must come before declarations)
        while self.check(TokenKind::Import) {
            imports.push(self.parse_import()?);
            self.skip_newlines();
        }

        while !self.is_at_end() {
            declarations.push(self.parse_declaration()?);
            self.skip_newlines();
        }

        Ok(Program {
            imports,
            declarations,
        })
    }

    /// Parse an import declaration
    fn parse_import(&mut self) -> Result<ImportDecl, ParseError> {
        let start = self.current_span();
        self.expect(TokenKind::Import)?;

        // Parse module path: foo/bar/baz
        let mut segments = vec![self.parse_ident()?];
        while self.check(TokenKind::Slash) {
            self.advance();
            segments.push(self.parse_ident()?);
        }
        let path_span = start.merge(self.previous_span());
        let path = ModulePath {
            segments,
            span: path_span,
        };

        // Check for wildcard import: import foo.*
        let wildcard = if self.check(TokenKind::Dot) && self.peek_next_kind() == TokenKind::Star {
            self.advance(); // .
            self.advance(); // *
            true
        } else {
            false
        };

        // Check for selective import: import foo.{a, b, c}
        let items = if !wildcard
            && self.check(TokenKind::Dot)
            && self.peek_next_kind() == TokenKind::LBrace
        {
            self.advance(); // .
            self.advance(); // {
            let mut items = Vec::new();
            while !self.check(TokenKind::RBrace) {
                items.push(self.parse_ident()?);
                if !self.check(TokenKind::RBrace) {
                    self.expect(TokenKind::Comma)?;
                }
            }
            self.expect(TokenKind::RBrace)?;
            Some(items)
        } else {
            None
        };

        // Check for alias: import foo as bar
        let alias = if self.check(TokenKind::As) {
            self.advance();
            Some(self.parse_ident()?)
        } else {
            None
        };

        let span = start.merge(self.previous_span());
        Ok(ImportDecl {
            path,
            alias,
            items,
            wildcard,
            span,
        })
    }

    /// Parse a top-level declaration
    fn parse_declaration(&mut self) -> Result<Declaration, ParseError> {
        self.skip_newlines();

        // Collect any doc comments before the declaration
        let doc = self.collect_doc_comments();

        // Check for visibility modifier
        let visibility = if self.check(TokenKind::Pub) {
            self.advance();
            Visibility::Public
        } else {
            Visibility::Private
        };

        match self.peek_kind() {
            TokenKind::Fn => Ok(Declaration::Function(self.parse_function_decl(visibility, doc)?)),
            TokenKind::Effect => Ok(Declaration::Effect(self.parse_effect_decl(doc)?)),
            TokenKind::Handler => Ok(Declaration::Handler(self.parse_handler_decl()?)),
            TokenKind::Type => Ok(Declaration::Type(self.parse_type_decl(visibility, doc)?)),
            TokenKind::Let => Ok(Declaration::Let(self.parse_let_decl(visibility, doc)?)),
            TokenKind::Trait => Ok(Declaration::Trait(self.parse_trait_decl(visibility, doc)?)),
            TokenKind::Impl => Ok(Declaration::Impl(self.parse_impl_decl()?)),
            TokenKind::Run => Err(self.error("Bare 'run' expressions are not allowed at top level. Use 'let _ = run ...' or 'let result = run ...'")),
            _ => Err(self.error("Expected declaration (fn, effect, handler, type, trait, impl, or let)")),
        }
    }

    /// Collect consecutive doc comments into a single string
    fn collect_doc_comments(&mut self) -> Option<String> {
        let mut docs = Vec::new();

        while let TokenKind::DocComment(content) = self.peek_kind() {
            docs.push(content.clone());
            self.advance();
            self.skip_newlines();
        }

        if docs.is_empty() {
            None
        } else {
            Some(docs.join("\n"))
        }
    }

    /// Parse a function declaration
    fn parse_function_decl(&mut self, visibility: Visibility, doc: Option<String>) -> Result<FunctionDecl, ParseError> {
        let start = self.current_span();
        self.expect(TokenKind::Fn)?;

        let name = self.parse_ident()?;

        // Optional type parameters
        let type_params = if self.check(TokenKind::Lt) {
            self.parse_type_params()?
        } else {
            Vec::new()
        };

        self.expect(TokenKind::LParen)?;
        let params = self.parse_params()?;
        self.expect(TokenKind::RParen)?;

        // Return type
        self.expect(TokenKind::Colon)?;
        let return_type = self.parse_type()?;

        // Optional effects
        let effects = if self.check(TokenKind::With) {
            self.advance();
            self.parse_effect_list()?
        } else {
            Vec::new()
        };

        // Optional behavioral properties: is pure, is total, etc.
        let properties = self.parse_behavioral_properties()?;

        // Optional where clauses
        let where_clauses = self.parse_where_clauses()?;

        self.expect(TokenKind::Eq)?;
        self.skip_newlines();
        let body = self.parse_expr()?;

        let span = start.merge(body.span());
        Ok(FunctionDecl {
            visibility,
            doc,
            name,
            type_params,
            params,
            return_type,
            effects,
            properties,
            where_clauses,
            body,
            span,
        })
    }

    /// Parse effect declaration
    fn parse_effect_decl(&mut self, doc: Option<String>) -> Result<EffectDecl, ParseError> {
        let start = self.current_span();
        self.expect(TokenKind::Effect)?;

        let name = self.parse_ident()?;

        let type_params = if self.check(TokenKind::Lt) {
            self.parse_type_params()?
        } else {
            Vec::new()
        };

        self.expect(TokenKind::LBrace)?;
        self.skip_newlines();

        let mut operations = Vec::new();
        while !self.check(TokenKind::RBrace) {
            operations.push(self.parse_effect_op()?);
            self.skip_newlines();
            // Optional comma or newline separator
            if self.check(TokenKind::Comma) {
                self.advance();
            }
            self.skip_newlines();
        }

        let end = self.current_span();
        self.expect(TokenKind::RBrace)?;

        Ok(EffectDecl {
            doc,
            name,
            type_params,
            operations,
            span: start.merge(end),
        })
    }

    /// Parse an effect operation
    fn parse_effect_op(&mut self) -> Result<EffectOp, ParseError> {
        let start = self.current_span();
        self.expect(TokenKind::Fn)?;

        let name = self.parse_ident()?;

        self.expect(TokenKind::LParen)?;
        let params = self.parse_params()?;
        self.expect(TokenKind::RParen)?;

        self.expect(TokenKind::Colon)?;
        let return_type = self.parse_type()?;

        let span = start.merge(self.previous_span());
        Ok(EffectOp {
            name,
            params,
            return_type,
            span,
        })
    }

    /// Parse handler declaration
    fn parse_handler_decl(&mut self) -> Result<HandlerDecl, ParseError> {
        let start = self.current_span();
        self.expect(TokenKind::Handler)?;

        let name = self.parse_ident()?;

        // Optional parameters
        let params = if self.check(TokenKind::LParen) {
            self.advance();
            let p = self.parse_params()?;
            self.expect(TokenKind::RParen)?;
            p
        } else {
            Vec::new()
        };

        self.expect(TokenKind::Colon)?;
        let effect = self.parse_ident()?;

        self.expect(TokenKind::LBrace)?;
        self.skip_newlines();

        let mut implementations = Vec::new();
        while !self.check(TokenKind::RBrace) {
            implementations.push(self.parse_handler_impl()?);
            self.skip_newlines();
        }

        let end = self.current_span();
        self.expect(TokenKind::RBrace)?;

        Ok(HandlerDecl {
            name,
            params,
            effect,
            implementations,
            span: start.merge(end),
        })
    }

    /// Parse handler implementation
    fn parse_handler_impl(&mut self) -> Result<HandlerImpl, ParseError> {
        let start = self.current_span();
        self.expect(TokenKind::Fn)?;

        let op_name = self.parse_ident()?;

        self.expect(TokenKind::LParen)?;
        let mut params = Vec::new();
        while !self.check(TokenKind::RParen) {
            params.push(self.parse_ident()?);
            if !self.check(TokenKind::RParen) {
                self.expect(TokenKind::Comma)?;
            }
        }
        self.expect(TokenKind::RParen)?;

        // Optional resume parameter
        let resume = if self.check(TokenKind::With) {
            self.advance();
            Some(self.parse_ident()?)
        } else {
            None
        };

        self.expect(TokenKind::Eq)?;
        self.skip_newlines();
        let body = self.parse_expr()?;

        let span = start.merge(body.span());
        Ok(HandlerImpl {
            op_name,
            params,
            resume,
            body,
            span,
        })
    }

    /// Parse type declaration
    fn parse_type_decl(&mut self, visibility: Visibility, doc: Option<String>) -> Result<TypeDecl, ParseError> {
        let start = self.current_span();
        self.expect(TokenKind::Type)?;

        let name = self.parse_ident()?;

        let type_params = if self.check(TokenKind::Lt) {
            self.parse_type_params()?
        } else {
            Vec::new()
        };

        // Check for version annotation: type User @v2 { ... }
        let version = if self.check(TokenKind::At) {
            Some(self.parse_version()?)
        } else {
            None
        };

        // Check what kind of type definition
        let definition = if self.check(TokenKind::LBrace) {
            // Record type
            self.advance();
            self.skip_newlines();
            let fields = self.parse_record_fields()?;
            self.skip_newlines();

            // Check for migrations inside the record: from @v1 = { ... }
            let migrations = self.parse_migrations()?;

            self.expect(TokenKind::RBrace)?;
            (TypeDef::Record(fields), migrations)
        } else if self.check(TokenKind::Eq) {
            self.advance();
            self.skip_newlines();

            if self.check(TokenKind::Pipe) {
                // Enum type - with leading | for variants
                (TypeDef::Enum(self.parse_variants()?), Vec::new())
            } else if self.is_single_line_enum() {
                // Single-line enum without leading pipe: type Status = Ok | Error
                (TypeDef::Enum(self.parse_single_line_variants()?), Vec::new())
            } else {
                // Type alias - any type expression
                (TypeDef::Alias(self.parse_type()?), Vec::new())
            }
        } else {
            return Err(self.error("Expected '=' or '{' in type declaration"));
        };

        let span = start.merge(self.previous_span());
        Ok(TypeDecl {
            visibility,
            doc,
            name,
            type_params,
            version,
            definition: definition.0,
            migrations: definition.1,
            span,
        })
    }

    /// Parse let declaration
    fn parse_let_decl(&mut self, visibility: Visibility, doc: Option<String>) -> Result<LetDecl, ParseError> {
        let start = self.current_span();
        self.expect(TokenKind::Let)?;

        // Allow underscore as wildcard pattern (discards the value)
        let name = if self.check(TokenKind::Underscore) {
            let span = self.current_span();
            self.advance();
            Ident::new("_".to_string(), span)
        } else {
            self.parse_ident()?
        };

        let typ = if self.check(TokenKind::Colon) {
            self.advance();
            Some(self.parse_type()?)
        } else {
            None
        };

        self.expect(TokenKind::Eq)?;
        self.skip_newlines();
        let value = self.parse_expr()?;

        let span = start.merge(value.span());
        Ok(LetDecl {
            visibility,
            doc,
            name,
            typ,
            value,
            span,
        })
    }

    /// Parse trait declaration: trait Show { fn show(self): String }
    fn parse_trait_decl(&mut self, visibility: Visibility, doc: Option<String>) -> Result<TraitDecl, ParseError> {
        let start = self.current_span();
        self.expect(TokenKind::Trait)?;

        let name = self.parse_ident()?;

        // Optional type parameters: trait Functor<F> { ... }
        let type_params = if self.check(TokenKind::Lt) {
            self.parse_type_params()?
        } else {
            Vec::new()
        };

        // Optional super traits: trait Ord: Eq { ... }
        let super_traits = if self.check(TokenKind::Colon) {
            self.advance();
            self.parse_trait_bounds()?
        } else {
            Vec::new()
        };

        self.expect(TokenKind::LBrace)?;
        self.skip_newlines();

        let mut methods = Vec::new();
        while !self.check(TokenKind::RBrace) {
            methods.push(self.parse_trait_method()?);
            self.skip_newlines();
            if self.check(TokenKind::Comma) {
                self.advance();
            }
            self.skip_newlines();
        }

        let end = self.current_span();
        self.expect(TokenKind::RBrace)?;

        Ok(TraitDecl {
            visibility,
            doc,
            name,
            type_params,
            super_traits,
            methods,
            span: start.merge(end),
        })
    }

    /// Parse a trait method signature
    fn parse_trait_method(&mut self) -> Result<TraitMethod, ParseError> {
        let start = self.current_span();
        self.expect(TokenKind::Fn)?;

        let name = self.parse_ident()?;

        // Optional type parameters
        let type_params = if self.check(TokenKind::Lt) {
            self.parse_type_params()?
        } else {
            Vec::new()
        };

        self.expect(TokenKind::LParen)?;
        let params = self.parse_params()?;
        self.expect(TokenKind::RParen)?;

        self.expect(TokenKind::Colon)?;
        let return_type = self.parse_type()?;

        // Optional default implementation
        let default_impl = if self.check(TokenKind::Eq) {
            self.advance();
            self.skip_newlines();
            Some(self.parse_expr()?)
        } else {
            None
        };

        let span = start.merge(self.previous_span());
        Ok(TraitMethod {
            name,
            type_params,
            params,
            return_type,
            default_impl,
            span,
        })
    }

    /// Parse trait bounds: Eq + Ord + Show
    fn parse_trait_bounds(&mut self) -> Result<Vec<TraitBound>, ParseError> {
        let mut bounds = Vec::new();

        loop {
            bounds.push(self.parse_trait_bound()?);

            if self.check(TokenKind::Plus) {
                self.advance();
            } else {
                break;
            }
        }

        Ok(bounds)
    }

    /// Parse a single trait bound: Show, Functor<F>
    fn parse_trait_bound(&mut self) -> Result<TraitBound, ParseError> {
        let start = self.current_span();
        let trait_name = self.parse_ident()?;

        let type_args = if self.check(TokenKind::Lt) {
            self.advance();
            let mut args = Vec::new();
            while !self.check(TokenKind::Gt) {
                args.push(self.parse_type()?);
                if !self.check(TokenKind::Gt) {
                    self.expect(TokenKind::Comma)?;
                }
            }
            self.expect(TokenKind::Gt)?;
            args
        } else {
            Vec::new()
        };

        let span = start.merge(self.previous_span());
        Ok(TraitBound {
            trait_name,
            type_args,
            span,
        })
    }

    /// Parse impl declaration: impl Show for Int { ... }
    fn parse_impl_decl(&mut self) -> Result<ImplDecl, ParseError> {
        let start = self.current_span();
        self.expect(TokenKind::Impl)?;

        // Optional type parameters: impl<T> Show for List<T> { ... }
        let type_params = if self.check(TokenKind::Lt) {
            self.parse_type_params()?
        } else {
            Vec::new()
        };

        // Parse the trait name
        let trait_name = self.parse_ident()?;

        // Optional type arguments for the trait: impl Functor<List> for ...
        let trait_args = if self.check(TokenKind::Lt) {
            self.advance();
            let mut args = Vec::new();
            while !self.check(TokenKind::Gt) {
                args.push(self.parse_type()?);
                if !self.check(TokenKind::Gt) {
                    self.expect(TokenKind::Comma)?;
                }
            }
            self.expect(TokenKind::Gt)?;
            args
        } else {
            Vec::new()
        };

        self.expect(TokenKind::For)?;
        let target_type = self.parse_type()?;

        // Optional where clause with trait constraints
        let constraints = if self.check(TokenKind::Where) {
            self.parse_trait_constraints()?
        } else {
            Vec::new()
        };

        self.expect(TokenKind::LBrace)?;
        self.skip_newlines();

        let mut methods = Vec::new();
        while !self.check(TokenKind::RBrace) {
            methods.push(self.parse_impl_method()?);
            self.skip_newlines();
            if self.check(TokenKind::Comma) {
                self.advance();
            }
            self.skip_newlines();
        }

        let end = self.current_span();
        self.expect(TokenKind::RBrace)?;

        Ok(ImplDecl {
            type_params,
            constraints,
            trait_name,
            trait_args,
            target_type,
            methods,
            span: start.merge(end),
        })
    }

    /// Parse trait constraints in a where clause: where T: Show, U: Eq + Ord
    fn parse_trait_constraints(&mut self) -> Result<Vec<TraitConstraint>, ParseError> {
        let mut constraints = Vec::new();

        while self.check(TokenKind::Where) {
            self.advance();
            let start = self.current_span();
            let type_param = self.parse_ident()?;
            self.expect(TokenKind::Colon)?;
            let bounds = self.parse_trait_bounds()?;
            let span = start.merge(self.previous_span());

            constraints.push(TraitConstraint {
                type_param,
                bounds,
                span,
            });

            if self.check(TokenKind::Comma) {
                self.advance();
            }
        }

        Ok(constraints)
    }

    /// Parse an impl method
    fn parse_impl_method(&mut self) -> Result<ImplMethod, ParseError> {
        let start = self.current_span();
        self.expect(TokenKind::Fn)?;

        let name = self.parse_ident()?;

        self.expect(TokenKind::LParen)?;
        let params = self.parse_params()?;
        self.expect(TokenKind::RParen)?;

        // Optional return type (infer if not provided)
        let return_type = if self.check(TokenKind::Colon) {
            self.advance();
            Some(self.parse_type()?)
        } else {
            None
        };

        self.expect(TokenKind::Eq)?;
        self.skip_newlines();
        let body = self.parse_expr()?;

        let span = start.merge(body.span());
        Ok(ImplMethod {
            name,
            params,
            return_type,
            body,
            span,
        })
    }

    /// Parse type parameters <A, B, C>
    fn parse_type_params(&mut self) -> Result<Vec<Ident>, ParseError> {
        self.expect(TokenKind::Lt)?;
        let mut params = Vec::new();

        while !self.check(TokenKind::Gt) {
            params.push(self.parse_ident()?);
            if !self.check(TokenKind::Gt) {
                self.expect(TokenKind::Comma)?;
            }
        }

        self.expect(TokenKind::Gt)?;
        Ok(params)
    }

    /// Parse function parameters
    fn parse_params(&mut self) -> Result<Vec<Parameter>, ParseError> {
        let mut params = Vec::new();

        while !self.check(TokenKind::RParen) {
            let start = self.current_span();
            let name = self.parse_ident()?;
            self.expect(TokenKind::Colon)?;
            let typ = self.parse_type()?;
            let span = start.merge(self.previous_span());

            params.push(Parameter { name, typ, span });

            if !self.check(TokenKind::RParen) {
                self.expect(TokenKind::Comma)?;
            }
        }

        Ok(params)
    }

    /// Parse effect list { Effect1, Effect2 }
    fn parse_effect_list(&mut self) -> Result<Vec<Ident>, ParseError> {
        self.expect(TokenKind::LBrace)?;
        let mut effects = Vec::new();

        while !self.check(TokenKind::RBrace) {
            effects.push(self.parse_ident()?);
            if !self.check(TokenKind::RBrace) {
                self.expect(TokenKind::Comma)?;
            }
        }

        self.expect(TokenKind::RBrace)?;
        Ok(effects)
    }

    /// Parse behavioral properties: is pure, total, idempotent, etc.
    /// Supports: `is pure`, `is pure is total`, `is pure, total`, `is pure, is total`
    fn parse_behavioral_properties(&mut self) -> Result<Vec<BehavioralProperty>, ParseError> {
        let mut properties = Vec::new();

        while self.check(TokenKind::Is) || self.check(TokenKind::Assume) {
            let is_assumed = self.check(TokenKind::Assume);
            self.advance(); // consume 'is' or 'assume'

            if is_assumed {
                // 'assume' must be followed by 'is'
                if !self.check(TokenKind::Is) {
                    return Err(ParseError {
                        message: "Expected 'is' after 'assume'".to_string(),
                        span: self.current_span(),
                    });
                }
                self.advance(); // consume 'is'
            }

            let property = self.parse_single_property()?;
            properties.push(property);

            // After first property, allow comma-separated list without repeating 'is'
            while self.check(TokenKind::Comma) {
                self.advance(); // consume comma
                // Allow optional 'is' after comma: `is pure, is total` or `is pure, total`
                if self.check(TokenKind::Is) {
                    self.advance();
                }
                let property = self.parse_single_property()?;
                properties.push(property);
            }
        }

        Ok(properties)
    }

    /// Parse a single behavioral property keyword
    fn parse_single_property(&mut self) -> Result<BehavioralProperty, ParseError> {
        let span = self.current_span();
        match self.peek_kind() {
            TokenKind::Pure => {
                self.advance();
                Ok(BehavioralProperty::Pure)
            }
            TokenKind::Total => {
                self.advance();
                Ok(BehavioralProperty::Total)
            }
            TokenKind::Idempotent => {
                self.advance();
                Ok(BehavioralProperty::Idempotent)
            }
            TokenKind::Deterministic => {
                self.advance();
                Ok(BehavioralProperty::Deterministic)
            }
            TokenKind::Commutative => {
                self.advance();
                Ok(BehavioralProperty::Commutative)
            }
            _ => Err(ParseError {
                message: "Expected behavioral property: pure, total, idempotent, deterministic, or commutative".to_string(),
                span,
            }),
        }
    }

    /// Parse where clauses: where F is pure, where result > 0
    fn parse_where_clauses(&mut self) -> Result<Vec<WhereClause>, ParseError> {
        let mut clauses = Vec::new();

        while self.check(TokenKind::Where) {
            self.advance(); // consume 'where'
            let span = self.current_span();

            // Check if it's a property constraint: where F is pure
            // or a result refinement: where result > 0
            if self.check_ident() {
                let ident = self.parse_ident()?;

                if self.check(TokenKind::Is) {
                    self.advance(); // consume 'is'
                    let property = self.parse_single_property()?;
                    clauses.push(WhereClause::PropertyConstraint {
                        type_param: ident,
                        property,
                        span,
                    });
                } else {
                    // This is a result refinement starting with an identifier
                    // For now, we'll parse it as a simple expression
                    // Put the identifier back by creating an expression
                    let predicate = self.parse_refinement_with_ident(ident)?;
                    clauses.push(WhereClause::ResultRefinement {
                        predicate: Box::new(predicate),
                        span,
                    });
                }
            } else {
                return Err(ParseError {
                    message: "Expected identifier after 'where'".to_string(),
                    span,
                });
            }

            // Optional comma for multiple where clauses
            if self.check(TokenKind::Comma) {
                self.advance();
            }
        }

        Ok(clauses)
    }

    /// Parse a refinement expression that starts with an already-parsed identifier
    fn parse_refinement_with_ident(&mut self, ident: Ident) -> Result<Expr, ParseError> {
        // Start with the identifier as a variable
        let mut left = Expr::Var(ident);

        // Parse the rest as a comparison expression
        if let Some(op) = self.try_parse_comparison_op() {
            let right = self.parse_primary_expr()?;
            let span = left.span().merge(right.span());
            left = Expr::BinaryOp {
                op,
                left: Box::new(left),
                right: Box::new(right),
                span,
            };
        }

        Ok(left)
    }

    /// Try to parse a comparison operator
    fn try_parse_comparison_op(&mut self) -> Option<BinaryOp> {
        match self.peek_kind() {
            TokenKind::Lt => {
                self.advance();
                Some(BinaryOp::Lt)
            }
            TokenKind::Le => {
                self.advance();
                Some(BinaryOp::Le)
            }
            TokenKind::Gt => {
                self.advance();
                Some(BinaryOp::Gt)
            }
            TokenKind::Ge => {
                self.advance();
                Some(BinaryOp::Ge)
            }
            TokenKind::EqEq => {
                self.advance();
                Some(BinaryOp::Eq)
            }
            TokenKind::Ne => {
                self.advance();
                Some(BinaryOp::Ne)
            }
            _ => None,
        }
    }

    /// Check if the current token is an identifier
    fn check_ident(&self) -> bool {
        matches!(self.peek_kind(), TokenKind::Ident(_))
    }

    /// Parse a type expression
    fn parse_type(&mut self) -> Result<TypeExpr, ParseError> {
        // Function type: fn(A, B): C with {E}
        if self.check(TokenKind::Fn) {
            return self.parse_function_type();
        }

        // Tuple or parenthesized type
        if self.check(TokenKind::LParen) {
            return self.parse_tuple_or_paren_type();
        }

        // Record type
        if self.check(TokenKind::LBrace) {
            return self.parse_record_type();
        }

        // Named type (possibly with type arguments)
        let name = self.parse_ident()?;

        // Check for type arguments
        let base_type = if self.check(TokenKind::Lt) {
            self.advance();
            let mut args = Vec::new();

            while !self.check(TokenKind::Gt) {
                args.push(self.parse_type()?);
                if !self.check(TokenKind::Gt) {
                    self.expect(TokenKind::Comma)?;
                }
            }

            self.expect(TokenKind::Gt)?;
            TypeExpr::App(Box::new(TypeExpr::Named(name)), args)
        } else {
            TypeExpr::Named(name)
        };

        // Check for version constraint: Type @v1, Type @v2+, Type @latest
        if self.check(TokenKind::At) {
            let constraint = self.parse_version_constraint()?;
            Ok(TypeExpr::Versioned {
                base: Box::new(base_type),
                constraint,
            })
        } else {
            Ok(base_type)
        }
    }

    fn parse_function_type(&mut self) -> Result<TypeExpr, ParseError> {
        self.expect(TokenKind::Fn)?;
        self.expect(TokenKind::LParen)?;

        let mut params = Vec::new();
        while !self.check(TokenKind::RParen) {
            params.push(self.parse_type()?);
            if !self.check(TokenKind::RParen) {
                self.expect(TokenKind::Comma)?;
            }
        }

        self.expect(TokenKind::RParen)?;
        self.expect(TokenKind::Colon)?;
        let return_type = Box::new(self.parse_type()?);

        let effects = if self.check(TokenKind::With) {
            self.advance();
            self.parse_effect_list()?
        } else {
            Vec::new()
        };

        Ok(TypeExpr::Function {
            params,
            return_type,
            effects,
        })
    }

    fn parse_tuple_or_paren_type(&mut self) -> Result<TypeExpr, ParseError> {
        self.expect(TokenKind::LParen)?;

        if self.check(TokenKind::RParen) {
            self.advance();
            return Ok(TypeExpr::Unit);
        }

        let first = self.parse_type()?;

        if self.check(TokenKind::Comma) {
            // Tuple type
            let mut elements = vec![first];
            while self.check(TokenKind::Comma) {
                self.advance();
                if self.check(TokenKind::RParen) {
                    break;
                }
                elements.push(self.parse_type()?);
            }
            self.expect(TokenKind::RParen)?;
            Ok(TypeExpr::Tuple(elements))
        } else {
            // Parenthesized type
            self.expect(TokenKind::RParen)?;
            Ok(first)
        }
    }

    fn parse_record_type(&mut self) -> Result<TypeExpr, ParseError> {
        self.expect(TokenKind::LBrace)?;
        self.skip_newlines();
        let fields = self.parse_record_fields()?;
        self.expect(TokenKind::RBrace)?;
        Ok(TypeExpr::Record(fields))
    }

    fn parse_record_fields(&mut self) -> Result<Vec<RecordField>, ParseError> {
        let mut fields = Vec::new();

        while !self.check(TokenKind::RBrace) && !self.check(TokenKind::From) {
            let start = self.current_span();
            let name = self.parse_ident()?;
            self.expect(TokenKind::Colon)?;
            let typ = self.parse_type()?;
            let span = start.merge(self.previous_span());

            fields.push(RecordField { name, typ, span });

            self.skip_newlines();
            if self.check(TokenKind::Comma) {
                self.advance();
            }
            self.skip_newlines();
        }

        Ok(fields)
    }

    /// Parse a version annotation: @v1, @v2, etc.
    fn parse_version(&mut self) -> Result<Version, ParseError> {
        let start = self.current_span();
        self.expect(TokenKind::At)?;

        // Expect an identifier like "v1", "v2"
        let ident = self.parse_ident()?;

        // Parse the version number from the identifier (e.g., "v1" -> 1)
        if !ident.name.starts_with('v') {
            return Err(ParseError {
                message: format!("Expected version like @v1, @v2, got @{}", ident.name),
                span: ident.span,
            });
        }

        let version_str = &ident.name[1..];
        let number = version_str.parse::<u32>().map_err(|_| ParseError {
            message: format!("Invalid version number: {}", version_str),
            span: ident.span,
        })?;

        let span = start.merge(ident.span);
        Ok(Version::new(number, span))
    }

    /// Parse a version constraint: @v1, @v1+, @latest
    fn parse_version_constraint(&mut self) -> Result<VersionConstraint, ParseError> {
        let start = self.current_span();
        self.expect(TokenKind::At)?;

        // Check for @latest
        if self.check(TokenKind::Latest) {
            self.advance();
            let span = start.merge(self.previous_span());
            return Ok(VersionConstraint::Latest(span));
        }

        // Parse version identifier (v1, v2, etc.)
        let ident = self.parse_ident()?;

        if !ident.name.starts_with('v') {
            return Err(ParseError {
                message: format!(
                    "Expected version like @v1, @v2, or @latest, got @{}",
                    ident.name
                ),
                span: ident.span,
            });
        }

        let version_str = &ident.name[1..];
        let number = version_str.parse::<u32>().map_err(|_| ParseError {
            message: format!("Invalid version number: {}", version_str),
            span: ident.span,
        })?;

        let span = start.merge(ident.span);
        let version = Version::new(number, span);

        // Check for + (at least this version)
        if self.check(TokenKind::Plus) {
            self.advance();
            Ok(VersionConstraint::AtLeast(version))
        } else {
            Ok(VersionConstraint::Exact(version))
        }
    }

    /// Parse migrations: from @v1 = { ... }, from @v2 = { ... }
    fn parse_migrations(&mut self) -> Result<Vec<Migration>, ParseError> {
        let mut migrations = Vec::new();

        while self.check(TokenKind::From) {
            let start = self.current_span();
            self.advance(); // consume 'from'

            let from_version = self.parse_version()?;

            self.expect(TokenKind::Eq)?;
            self.skip_newlines();

            // Parse the migration body (an expression, typically a record literal)
            let body = self.parse_expr()?;

            let span = start.merge(body.span());
            migrations.push(Migration {
                from_version,
                body,
                span,
            });

            self.skip_newlines();
            // Optional comma between migrations
            if self.check(TokenKind::Comma) {
                self.advance();
            }
            self.skip_newlines();
        }

        Ok(migrations)
    }

    /// Check if we're looking at a single-line enum (no leading pipe)
    /// e.g., type Status = Ok | Error
    fn is_single_line_enum(&self) -> bool {
        // Look for pattern: Ident (LParen|LBrace)? Pipe
        // We need to peek ahead without consuming tokens
        if !matches!(&self.peek().kind, TokenKind::Ident(_)) {
            return false;
        }

        // Check if there's a | somewhere on this logical line
        // This is a simple heuristic - look at the next few tokens
        let mut pos = self.pos;
        let mut found_ident = false;
        let mut depth = 0;

        while pos < self.tokens.len() {
            match &self.tokens[pos].kind {
                TokenKind::Ident(_) if !found_ident => found_ident = true,
                TokenKind::LParen | TokenKind::LBrace => depth += 1,
                TokenKind::RParen | TokenKind::RBrace => {
                    if depth > 0 {
                        depth -= 1;
                    }
                }
                TokenKind::Pipe if depth == 0 => return true,
                TokenKind::Newline | TokenKind::Eof => return false,
                _ => {}
            }
            pos += 1;
        }
        false
    }

    /// Parse single-line variants without leading pipe
    fn parse_single_line_variants(&mut self) -> Result<Vec<Variant>, ParseError> {
        let mut variants = Vec::new();

        loop {
            let start = self.current_span();
            let name = self.parse_ident()?;

            let fields = if self.check(TokenKind::LParen) {
                // Tuple variant
                self.advance();
                let mut types = Vec::new();
                while !self.check(TokenKind::RParen) {
                    types.push(self.parse_type()?);
                    if !self.check(TokenKind::RParen) {
                        self.expect(TokenKind::Comma)?;
                    }
                }
                self.expect(TokenKind::RParen)?;
                VariantFields::Tuple(types)
            } else if self.check(TokenKind::LBrace) {
                // Record variant
                self.advance();
                self.skip_newlines();
                let fields = self.parse_record_fields()?;
                self.expect(TokenKind::RBrace)?;
                VariantFields::Record(fields)
            } else {
                VariantFields::Unit
            };

            let span = start.merge(self.previous_span());
            variants.push(Variant { name, fields, span });

            // Check for more variants
            if self.check(TokenKind::Pipe) {
                self.advance();
                self.skip_newlines();
            } else {
                break;
            }
        }

        Ok(variants)
    }

    fn parse_variants(&mut self) -> Result<Vec<Variant>, ParseError> {
        let mut variants = Vec::new();

        // Skip leading pipe
        if self.check(TokenKind::Pipe) {
            self.advance();
        }

        loop {
            let start = self.current_span();
            let name = self.parse_ident()?;

            let fields = if self.check(TokenKind::LParen) {
                // Tuple variant
                self.advance();
                let mut types = Vec::new();
                while !self.check(TokenKind::RParen) {
                    types.push(self.parse_type()?);
                    if !self.check(TokenKind::RParen) {
                        self.expect(TokenKind::Comma)?;
                    }
                }
                self.expect(TokenKind::RParen)?;
                VariantFields::Tuple(types)
            } else if self.check(TokenKind::LBrace) {
                // Record variant
                self.advance();
                self.skip_newlines();
                let fields = self.parse_record_fields()?;
                self.expect(TokenKind::RBrace)?;
                VariantFields::Record(fields)
            } else {
                VariantFields::Unit
            };

            let span = start.merge(self.previous_span());
            variants.push(Variant { name, fields, span });

            self.skip_newlines();
            if self.check(TokenKind::Pipe) {
                self.advance();
                self.skip_newlines();
            } else {
                break;
            }
        }

        Ok(variants)
    }

    fn peek_is_variant(&self) -> bool {
        matches!(self.peek_kind(), TokenKind::Ident(_))
    }

    /// Parse an expression
    fn parse_expr(&mut self) -> Result<Expr, ParseError> {
        self.parse_pipe_expr()
    }

    /// Parse pipe expressions: a |> b |> c
    fn parse_pipe_expr(&mut self) -> Result<Expr, ParseError> {
        let mut expr = self.parse_or_expr()?;

        while self.check(TokenKind::PipeGt) {
            let start = expr.span();
            self.advance();
            self.skip_newlines();
            let right = self.parse_or_expr()?;
            let span = start.merge(right.span());

            // Transform a |> f into f(a)
            expr = Expr::Call {
                func: Box::new(right),
                args: vec![expr],
                span,
            };
        }

        Ok(expr)
    }

    /// Parse or expressions: a || b
    fn parse_or_expr(&mut self) -> Result<Expr, ParseError> {
        let mut expr = self.parse_and_expr()?;

        while self.check(TokenKind::Or) {
            let start = expr.span();
            self.advance();
            self.skip_newlines();
            let right = self.parse_and_expr()?;
            let span = start.merge(right.span());
            expr = Expr::BinaryOp {
                op: BinaryOp::Or,
                left: Box::new(expr),
                right: Box::new(right),
                span,
            };
        }

        Ok(expr)
    }

    /// Parse and expressions: a && b
    fn parse_and_expr(&mut self) -> Result<Expr, ParseError> {
        let mut expr = self.parse_equality_expr()?;

        while self.check(TokenKind::And) {
            let start = expr.span();
            self.advance();
            self.skip_newlines();
            let right = self.parse_equality_expr()?;
            let span = start.merge(right.span());
            expr = Expr::BinaryOp {
                op: BinaryOp::And,
                left: Box::new(expr),
                right: Box::new(right),
                span,
            };
        }

        Ok(expr)
    }

    /// Parse equality expressions: a == b, a != b
    fn parse_equality_expr(&mut self) -> Result<Expr, ParseError> {
        let mut expr = self.parse_comparison_expr()?;

        loop {
            let op = match self.peek_kind() {
                TokenKind::EqEq => BinaryOp::Eq,
                TokenKind::Ne => BinaryOp::Ne,
                _ => break,
            };

            let start = expr.span();
            self.advance();
            self.skip_newlines();
            let right = self.parse_comparison_expr()?;
            let span = start.merge(right.span());
            expr = Expr::BinaryOp {
                op,
                left: Box::new(expr),
                right: Box::new(right),
                span,
            };
        }

        Ok(expr)
    }

    /// Parse comparison expressions: a < b, a <= b, etc.
    fn parse_comparison_expr(&mut self) -> Result<Expr, ParseError> {
        let mut expr = self.parse_additive_expr()?;

        loop {
            let op = match self.peek_kind() {
                TokenKind::Lt => BinaryOp::Lt,
                TokenKind::Le => BinaryOp::Le,
                TokenKind::Gt => BinaryOp::Gt,
                TokenKind::Ge => BinaryOp::Ge,
                _ => break,
            };

            let start = expr.span();
            self.advance();
            self.skip_newlines();
            let right = self.parse_additive_expr()?;
            let span = start.merge(right.span());
            expr = Expr::BinaryOp {
                op,
                left: Box::new(expr),
                right: Box::new(right),
                span,
            };
        }

        Ok(expr)
    }

    /// Parse additive expressions: a + b, a - b
    fn parse_additive_expr(&mut self) -> Result<Expr, ParseError> {
        let mut expr = self.parse_multiplicative_expr()?;

        loop {
            let op = match self.peek_kind() {
                TokenKind::Plus => BinaryOp::Add,
                TokenKind::Minus => BinaryOp::Sub,
                _ => break,
            };

            let start = expr.span();
            self.advance();
            self.skip_newlines();
            let right = self.parse_multiplicative_expr()?;
            let span = start.merge(right.span());
            expr = Expr::BinaryOp {
                op,
                left: Box::new(expr),
                right: Box::new(right),
                span,
            };
        }

        Ok(expr)
    }

    /// Parse multiplicative expressions: a * b, a / b, a % b
    fn parse_multiplicative_expr(&mut self) -> Result<Expr, ParseError> {
        let mut expr = self.parse_unary_expr()?;

        loop {
            let op = match self.peek_kind() {
                TokenKind::Star => BinaryOp::Mul,
                TokenKind::Slash => BinaryOp::Div,
                TokenKind::Percent => BinaryOp::Mod,
                _ => break,
            };

            let start = expr.span();
            self.advance();
            self.skip_newlines();
            let right = self.parse_unary_expr()?;
            let span = start.merge(right.span());
            expr = Expr::BinaryOp {
                op,
                left: Box::new(expr),
                right: Box::new(right),
                span,
            };
        }

        Ok(expr)
    }

    /// Parse unary expressions: -a, !a
    fn parse_unary_expr(&mut self) -> Result<Expr, ParseError> {
        let op = match self.peek_kind() {
            TokenKind::Minus => UnaryOp::Neg,
            TokenKind::Not => UnaryOp::Not,
            _ => return self.parse_call_expr(),
        };

        let start = self.current_span();
        self.advance();
        let operand = self.parse_unary_expr()?;
        let span = start.merge(operand.span());

        Ok(Expr::UnaryOp {
            op,
            operand: Box::new(operand),
            span,
        })
    }

    /// Parse call and field access expressions
    fn parse_call_expr(&mut self) -> Result<Expr, ParseError> {
        let mut expr = self.parse_primary_expr()?;

        loop {
            if self.check(TokenKind::LParen) {
                // Function call
                let start = expr.span();
                self.advance();
                let args = self.parse_args()?;
                self.expect(TokenKind::RParen)?;
                let span = start.merge(self.previous_span());
                expr = Expr::Call {
                    func: Box::new(expr),
                    args,
                    span,
                };
            } else if self.check(TokenKind::Dot) {
                let start = expr.span();
                self.advance();
                let field = self.parse_ident()?;

                // Check if this is an effect operation: Effect.operation(args)
                if self.check(TokenKind::LParen) {
                    if let Expr::Var(effect) = expr {
                        self.advance();
                        let args = self.parse_args()?;
                        self.expect(TokenKind::RParen)?;
                        let span = start.merge(self.previous_span());
                        expr = Expr::EffectOp {
                            effect,
                            operation: field,
                            args,
                            span,
                        };
                        continue;
                    }
                }

                let span = start.merge(field.span);
                expr = Expr::Field {
                    object: Box::new(expr),
                    field,
                    span,
                };
            } else {
                break;
            }
        }

        Ok(expr)
    }

    fn parse_args(&mut self) -> Result<Vec<Expr>, ParseError> {
        let mut args = Vec::new();

        while !self.check(TokenKind::RParen) {
            args.push(self.parse_expr()?);
            if !self.check(TokenKind::RParen) {
                self.expect(TokenKind::Comma)?;
            }
        }

        Ok(args)
    }

    /// Parse primary expressions
    fn parse_primary_expr(&mut self) -> Result<Expr, ParseError> {
        let token = self.peek().clone();

        match &token.kind {
            // Literals
            TokenKind::Int(n) => {
                let n = *n;
                self.advance();
                Ok(Expr::Literal(Literal {
                    kind: LiteralKind::Int(n),
                    span: token.span,
                }))
            }
            TokenKind::Float(f) => {
                let f = *f;
                self.advance();
                Ok(Expr::Literal(Literal {
                    kind: LiteralKind::Float(f),
                    span: token.span,
                }))
            }
            TokenKind::String(s) => {
                let s = s.clone();
                self.advance();
                Ok(Expr::Literal(Literal {
                    kind: LiteralKind::String(s),
                    span: token.span,
                }))
            }
            TokenKind::InterpolatedString(parts) => {
                let parts = parts.clone();
                let span = token.span;
                self.advance();
                self.desugar_interpolated_string(&parts, span)
            }
            TokenKind::Char(c) => {
                let c = *c;
                self.advance();
                Ok(Expr::Literal(Literal {
                    kind: LiteralKind::Char(c),
                    span: token.span,
                }))
            }
            TokenKind::Bool(b) => {
                let b = *b;
                self.advance();
                Ok(Expr::Literal(Literal {
                    kind: LiteralKind::Bool(b),
                    span: token.span,
                }))
            }

            // Identifiers
            TokenKind::Ident(_) => {
                let ident = self.parse_ident()?;
                Ok(Expr::Var(ident))
            }

            // Keywords that start expressions
            TokenKind::If => self.parse_if_expr(),
            TokenKind::Match => self.parse_match_expr(),
            TokenKind::Let => self.parse_let_expr(),
            TokenKind::Fn => self.parse_lambda_expr(),
            TokenKind::Run => self.parse_run_expr(),
            TokenKind::Resume => self.parse_resume_expr(),

            // Delimiters
            TokenKind::LParen => self.parse_tuple_or_paren_expr(),
            TokenKind::LBrace => self.parse_block_or_record_expr(),
            TokenKind::LBracket => self.parse_list_expr(),

            _ => Err(self.error(&format!("Unexpected token: {}", token.kind))),
        }
    }

    fn parse_if_expr(&mut self) -> Result<Expr, ParseError> {
        let start = self.current_span();
        self.expect(TokenKind::If)?;

        let condition = Box::new(self.parse_expr()?);

        self.expect(TokenKind::Then)?;
        self.skip_newlines();
        let then_branch = Box::new(self.parse_expr()?);

        self.skip_newlines();

        // Else is optional - if missing, synthesize a Unit value
        let else_branch = if self.check(TokenKind::Else) {
            self.expect(TokenKind::Else)?;
            self.skip_newlines();
            Box::new(self.parse_expr()?)
        } else {
            // No else clause - use Unit as the else branch
            Box::new(Expr::Literal(Literal {
                kind: LiteralKind::Unit,
                span: then_branch.span(),
            }))
        };

        let span = start.merge(else_branch.span());
        Ok(Expr::If {
            condition,
            then_branch,
            else_branch,
            span,
        })
    }

    fn parse_match_expr(&mut self) -> Result<Expr, ParseError> {
        let start = self.current_span();
        self.expect(TokenKind::Match)?;

        let scrutinee = Box::new(self.parse_expr()?);

        self.expect(TokenKind::LBrace)?;
        self.skip_newlines();

        let mut arms = Vec::new();
        while !self.check(TokenKind::RBrace) {
            arms.push(self.parse_match_arm()?);
            self.skip_newlines();
            if self.check(TokenKind::Comma) {
                self.advance();
            }
            self.skip_newlines();
        }

        let end = self.current_span();
        self.expect(TokenKind::RBrace)?;

        Ok(Expr::Match {
            scrutinee,
            arms,
            span: start.merge(end),
        })
    }

    fn parse_match_arm(&mut self) -> Result<MatchArm, ParseError> {
        let start = self.current_span();
        let pattern = self.parse_pattern()?;

        let guard = if self.check(TokenKind::If) {
            self.advance();
            Some(self.parse_expr()?)
        } else {
            None
        };

        self.expect(TokenKind::Arrow)?;
        self.skip_newlines();
        let body = self.parse_expr()?;

        let span = start.merge(body.span());
        Ok(MatchArm {
            pattern,
            guard,
            body,
            span,
        })
    }

    fn parse_pattern(&mut self) -> Result<Pattern, ParseError> {
        let token = self.peek().clone();

        match &token.kind {
            TokenKind::Underscore => {
                self.advance();
                Ok(Pattern::Wildcard(token.span))
            }
            TokenKind::Int(n) => {
                let n = *n;
                self.advance();
                Ok(Pattern::Literal(Literal {
                    kind: LiteralKind::Int(n),
                    span: token.span,
                }))
            }
            TokenKind::String(s) => {
                let s = s.clone();
                self.advance();
                Ok(Pattern::Literal(Literal {
                    kind: LiteralKind::String(s),
                    span: token.span,
                }))
            }
            TokenKind::Bool(b) => {
                let b = *b;
                self.advance();
                Ok(Pattern::Literal(Literal {
                    kind: LiteralKind::Bool(b),
                    span: token.span,
                }))
            }
            TokenKind::Char(c) => {
                let c = *c;
                self.advance();
                Ok(Pattern::Literal(Literal {
                    kind: LiteralKind::Char(c),
                    span: token.span,
                }))
            }
            TokenKind::Ident(name) => {
                // Check if it starts with uppercase (constructor) or lowercase (variable)
                if name.chars().next().map_or(false, |c| c.is_uppercase()) {
                    self.parse_constructor_pattern()
                } else {
                    let ident = self.parse_ident()?;
                    Ok(Pattern::Var(ident))
                }
            }
            TokenKind::LParen => self.parse_tuple_pattern(),
            TokenKind::LBrace => self.parse_record_pattern(),
            _ => Err(self.error("Expected pattern")),
        }
    }

    fn parse_constructor_pattern(&mut self) -> Result<Pattern, ParseError> {
        let start = self.current_span();
        let name = self.parse_ident()?;

        if self.check(TokenKind::LParen) {
            self.advance();
            let mut fields = Vec::new();
            while !self.check(TokenKind::RParen) {
                fields.push(self.parse_pattern()?);
                if !self.check(TokenKind::RParen) {
                    self.expect(TokenKind::Comma)?;
                }
            }
            self.expect(TokenKind::RParen)?;
            let span = start.merge(self.previous_span());
            Ok(Pattern::Constructor { name, fields, span })
        } else {
            let span = name.span;
            Ok(Pattern::Constructor {
                name,
                fields: Vec::new(),
                span,
            })
        }
    }

    fn parse_tuple_pattern(&mut self) -> Result<Pattern, ParseError> {
        let start = self.current_span();
        self.expect(TokenKind::LParen)?;

        let mut elements = Vec::new();
        while !self.check(TokenKind::RParen) {
            elements.push(self.parse_pattern()?);
            if !self.check(TokenKind::RParen) {
                self.expect(TokenKind::Comma)?;
            }
        }

        self.expect(TokenKind::RParen)?;
        let span = start.merge(self.previous_span());
        Ok(Pattern::Tuple { elements, span })
    }

    fn parse_record_pattern(&mut self) -> Result<Pattern, ParseError> {
        let start = self.current_span();
        self.expect(TokenKind::LBrace)?;
        self.skip_newlines();

        let mut fields = Vec::new();
        while !self.check(TokenKind::RBrace) {
            let name = self.parse_ident()?;
            let pattern = if self.check(TokenKind::Colon) {
                self.advance();
                self.parse_pattern()?
            } else {
                Pattern::Var(name.clone())
            };
            fields.push((name, pattern));

            self.skip_newlines();
            if self.check(TokenKind::Comma) {
                self.advance();
            }
            self.skip_newlines();
        }

        self.expect(TokenKind::RBrace)?;
        let span = start.merge(self.previous_span());
        Ok(Pattern::Record { fields, span })
    }

    fn parse_let_expr(&mut self) -> Result<Expr, ParseError> {
        let start = self.current_span();
        self.expect(TokenKind::Let)?;

        // Allow underscore as wildcard pattern (discards the value)
        let name = if self.check(TokenKind::Underscore) {
            let span = self.current_span();
            self.advance();
            Ident::new("_".to_string(), span)
        } else {
            self.parse_ident()?
        };

        let typ = if self.check(TokenKind::Colon) {
            self.advance();
            Some(self.parse_type()?)
        } else {
            None
        };

        self.expect(TokenKind::Eq)?;
        self.skip_newlines();
        let value = Box::new(self.parse_expr()?);

        // Check for semicolon (let-in style)
        self.skip_newlines();
        if self.check(TokenKind::Semi) {
            self.advance();
            self.skip_newlines();
            let body = Box::new(self.parse_expr()?);
            let span = start.merge(body.span());
            Ok(Expr::Let {
                name,
                typ,
                value,
                body,
                span,
            })
        } else {
            // Let as expression (returns unit)
            let span = start.merge(value.span());
            let body = Box::new(Expr::Literal(Literal {
                kind: LiteralKind::Unit,
                span: Span::default(),
            }));
            Ok(Expr::Let {
                name,
                typ,
                value,
                body,
                span,
            })
        }
    }

    fn parse_lambda_expr(&mut self) -> Result<Expr, ParseError> {
        let start = self.current_span();
        self.expect(TokenKind::Fn)?;

        self.expect(TokenKind::LParen)?;
        let params = self.parse_lambda_params()?;
        self.expect(TokenKind::RParen)?;

        let return_type = if self.check(TokenKind::Colon) {
            self.advance();
            Some(Box::new(self.parse_type()?))
        } else {
            None
        };

        let effects = if self.check(TokenKind::With) {
            self.advance();
            self.parse_effect_list()?
        } else {
            Vec::new()
        };

        self.expect(TokenKind::Arrow)?;
        self.skip_newlines();
        let body = Box::new(self.parse_expr()?);

        let span = start.merge(body.span());
        Ok(Expr::Lambda {
            params,
            return_type,
            effects,
            body,
            span,
        })
    }

    fn parse_lambda_params(&mut self) -> Result<Vec<Parameter>, ParseError> {
        let mut params = Vec::new();

        while !self.check(TokenKind::RParen) {
            let start = self.current_span();
            let name = self.parse_ident()?;

            let typ = if self.check(TokenKind::Colon) {
                self.advance();
                self.parse_type()?
            } else {
                // Infer type later
                TypeExpr::Named(Ident::new("_", Span::default()))
            };

            let span = start.merge(self.previous_span());
            params.push(Parameter { name, typ, span });

            if !self.check(TokenKind::RParen) {
                self.expect(TokenKind::Comma)?;
            }
        }

        Ok(params)
    }

    fn parse_run_expr(&mut self) -> Result<Expr, ParseError> {
        let start = self.current_span();
        self.expect(TokenKind::Run)?;

        let expr = Box::new(self.parse_call_expr()?);

        self.expect(TokenKind::With)?;
        self.expect(TokenKind::LBrace)?;
        self.skip_newlines();

        let mut handlers = Vec::new();
        while !self.check(TokenKind::RBrace) {
            let effect = self.parse_ident()?;
            self.expect(TokenKind::Eq)?;
            let handler = self.parse_expr()?;
            handlers.push((effect, handler));

            self.skip_newlines();
            if self.check(TokenKind::Comma) {
                self.advance();
            }
            self.skip_newlines();
        }

        let end = self.current_span();
        self.expect(TokenKind::RBrace)?;

        Ok(Expr::Run {
            expr,
            handlers,
            span: start.merge(end),
        })
    }

    fn parse_resume_expr(&mut self) -> Result<Expr, ParseError> {
        let start = self.current_span();
        self.expect(TokenKind::Resume)?;
        self.expect(TokenKind::LParen)?;
        let value = Box::new(self.parse_expr()?);
        self.expect(TokenKind::RParen)?;
        let span = start.merge(self.previous_span());
        Ok(Expr::Resume { value, span })
    }

    fn parse_tuple_or_paren_expr(&mut self) -> Result<Expr, ParseError> {
        let start = self.current_span();
        self.expect(TokenKind::LParen)?;

        if self.check(TokenKind::RParen) {
            self.advance();
            return Ok(Expr::Literal(Literal {
                kind: LiteralKind::Unit,
                span: start.merge(self.previous_span()),
            }));
        }

        let first = self.parse_expr()?;

        if self.check(TokenKind::Comma) {
            // Tuple
            let mut elements = vec![first];
            while self.check(TokenKind::Comma) {
                self.advance();
                if self.check(TokenKind::RParen) {
                    break;
                }
                elements.push(self.parse_expr()?);
            }
            self.expect(TokenKind::RParen)?;
            let span = start.merge(self.previous_span());
            Ok(Expr::Tuple { elements, span })
        } else {
            // Parenthesized expression
            self.expect(TokenKind::RParen)?;
            Ok(first)
        }
    }

    fn parse_block_or_record_expr(&mut self) -> Result<Expr, ParseError> {
        let start = self.current_span();
        self.expect(TokenKind::LBrace)?;
        self.skip_newlines();

        // Empty block
        if self.check(TokenKind::RBrace) {
            self.advance();
            return Ok(Expr::Literal(Literal {
                kind: LiteralKind::Unit,
                span: start.merge(self.previous_span()),
            }));
        }

        // Check if it's a record (ident: expr) or block
        if matches!(self.peek_kind(), TokenKind::Ident(_)) {
            let lookahead = self.tokens.get(self.pos + 1).map(|t| &t.kind);
            if matches!(lookahead, Some(TokenKind::Colon)) {
                return self.parse_record_expr_rest(start);
            }
        }

        // It's a block
        self.parse_block_rest(start)
    }

    fn parse_record_expr_rest(&mut self, start: Span) -> Result<Expr, ParseError> {
        let mut fields = Vec::new();

        while !self.check(TokenKind::RBrace) {
            let name = self.parse_ident()?;
            self.expect(TokenKind::Colon)?;
            let value = self.parse_expr()?;
            fields.push((name, value));

            self.skip_newlines();
            if self.check(TokenKind::Comma) {
                self.advance();
            }
            self.skip_newlines();
        }

        self.expect(TokenKind::RBrace)?;
        let span = start.merge(self.previous_span());
        Ok(Expr::Record { fields, span })
    }

    fn parse_block_rest(&mut self, start: Span) -> Result<Expr, ParseError> {
        let mut statements = Vec::new();

        loop {
            self.skip_newlines();

            if self.check(TokenKind::RBrace) {
                break;
            }

            if self.check(TokenKind::Let) {
                // Let statement
                let let_start = self.current_span();
                self.advance();

                // Allow underscore as wildcard pattern (discards the value)
                let name = if self.check(TokenKind::Underscore) {
                    let span = self.current_span();
                    self.advance();
                    Ident::new("_".to_string(), span)
                } else {
                    self.parse_ident()?
                };

                let typ = if self.check(TokenKind::Colon) {
                    self.advance();
                    Some(self.parse_type()?)
                } else {
                    None
                };

                self.expect(TokenKind::Eq)?;
                self.skip_newlines();
                let value = self.parse_expr()?;
                let span = let_start.merge(value.span());

                statements.push(Statement::Let {
                    name,
                    typ,
                    value,
                    span,
                });
            } else {
                // Expression statement
                let expr = self.parse_expr()?;
                statements.push(Statement::Expr(expr));
            }

            self.skip_newlines();

            // Optional semicolon
            if self.check(TokenKind::Semi) {
                self.advance();
            }

            self.skip_newlines();
        }

        // The last statement is the result
        let result = if let Some(Statement::Expr(expr)) = statements.pop() {
            Box::new(expr)
        } else {
            Box::new(Expr::Literal(Literal {
                kind: LiteralKind::Unit,
                span: Span::default(),
            }))
        };

        self.expect(TokenKind::RBrace)?;
        let span = start.merge(self.previous_span());

        Ok(Expr::Block {
            statements,
            result,
            span,
        })
    }

    fn parse_list_expr(&mut self) -> Result<Expr, ParseError> {
        let start = self.current_span();
        self.expect(TokenKind::LBracket)?;
        self.skip_newlines();

        let mut elements = Vec::new();
        while !self.check(TokenKind::RBracket) {
            elements.push(self.parse_expr()?);
            self.skip_newlines();
            if !self.check(TokenKind::RBracket) {
                self.expect(TokenKind::Comma)?;
                self.skip_newlines();
            }
        }

        self.expect(TokenKind::RBracket)?;
        let span = start.merge(self.previous_span());
        Ok(Expr::List { elements, span })
    }

    /// Desugar an interpolated string into concatenation with toString calls
    /// "Hello, {name}!" becomes "Hello, " + toString(name) + "!"
    fn desugar_interpolated_string(
        &mut self,
        parts: &[StringPart],
        span: Span,
    ) -> Result<Expr, ParseError> {
        let mut exprs: Vec<Expr> = Vec::new();

        for part in parts {
            match part {
                StringPart::Literal(s) => {
                    exprs.push(Expr::Literal(Literal {
                        kind: LiteralKind::String(s.clone()),
                        span,
                    }));
                }
                StringPart::Expr(expr_text) => {
                    // Parse the expression text
                    let lexer = Lexer::new(expr_text);
                    let tokens = lexer.tokenize().map_err(|e| ParseError {
                        message: format!("Lexer error in interpolation: {}", e.message),
                        span,
                    })?;

                    let mut parser = Parser::new(tokens);
                    let inner_expr = parser.parse_expr().map_err(|e| ParseError {
                        message: format!("Parse error in interpolation: {}", e.message),
                        span,
                    })?;

                    // Wrap the expression in toString() call
                    let to_string_call = Expr::Call {
                        func: Box::new(Expr::Var(Ident::new("toString".to_string(), span))),
                        args: vec![inner_expr],
                        span,
                    };
                    exprs.push(to_string_call);
                }
            }
        }

        // Chain all expressions with + operator
        if exprs.is_empty() {
            return Ok(Expr::Literal(Literal {
                kind: LiteralKind::String(String::new()),
                span,
            }));
        }

        let mut result = exprs.remove(0);
        for expr in exprs {
            result = Expr::BinaryOp {
                op: BinaryOp::Add,
                left: Box::new(result),
                right: Box::new(expr),
                span,
            };
        }

        Ok(result)
    }

    // Helper methods

    fn parse_ident(&mut self) -> Result<Ident, ParseError> {
        let token = self.peek().clone();
        match &token.kind {
            TokenKind::Ident(name) => {
                let name = name.clone();
                self.advance();
                Ok(Ident::new(name, token.span))
            }
            _ => Err(self.error("Expected identifier")),
        }
    }

    fn peek(&self) -> &Token {
        self.tokens.get(self.pos).unwrap_or(&self.eof_token)
    }

    fn peek_kind(&self) -> TokenKind {
        self.peek().kind.clone()
    }

    fn peek_next(&self) -> &Token {
        self.tokens.get(self.pos + 1).unwrap_or(&self.eof_token)
    }

    fn peek_next_kind(&self) -> TokenKind {
        self.peek_next().kind.clone()
    }

    fn advance(&mut self) -> &Token {
        if !self.is_at_end() {
            self.pos += 1;
        }
        self.tokens.get(self.pos - 1).unwrap()
    }

    fn check(&self, kind: TokenKind) -> bool {
        std::mem::discriminant(&self.peek_kind()) == std::mem::discriminant(&kind)
    }

    fn expect(&mut self, kind: TokenKind) -> Result<&Token, ParseError> {
        if self.check(kind.clone()) {
            Ok(self.advance())
        } else {
            Err(self.error(&format!("Expected {}, found {}", kind, self.peek_kind())))
        }
    }

    fn is_at_end(&self) -> bool {
        matches!(self.peek_kind(), TokenKind::Eof)
    }

    fn skip_newlines(&mut self) {
        while self.check(TokenKind::Newline) {
            self.advance();
        }
    }

    fn current_span(&self) -> Span {
        self.peek().span
    }

    fn previous_span(&self) -> Span {
        self.tokens
            .get(self.pos.saturating_sub(1))
            .map(|t| t.span)
            .unwrap_or_default()
    }

    fn error(&self, message: &str) -> ParseError {
        ParseError {
            message: message.to_string(),
            span: self.current_span(),
        }
    }
}

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

    #[test]
    fn test_parse_function() {
        let source = "fn add(a: Int, b: Int): Int = a + b";
        let program = Parser::parse_source(source).unwrap();
        assert_eq!(program.declarations.len(), 1);
    }

    #[test]
    fn test_parse_effect() {
        let source = r#"
            effect Console {
                fn print(msg: String): Unit
                fn read(): String
            }
        "#;
        let program = Parser::parse_source(source).unwrap();
        assert_eq!(program.declarations.len(), 1);
    }

    #[test]
    fn test_parse_if_expr() {
        let source = "fn max(a: Int, b: Int): Int = if a > b then a else b";
        let program = Parser::parse_source(source).unwrap();
        assert_eq!(program.declarations.len(), 1);
    }

    #[test]
    fn test_parse_lambda() {
        let source = "let f = fn(x: Int): Int => x + 1";
        let program = Parser::parse_source(source).unwrap();
        assert_eq!(program.declarations.len(), 1);
    }

    #[test]
    fn test_parse_import() {
        let source = r#"
            import std/list
            fn foo(): Int = 42
        "#;
        let program = Parser::parse_source(source).unwrap();
        assert_eq!(program.imports.len(), 1);
        assert_eq!(program.imports[0].path.segments.len(), 2);
        assert_eq!(program.imports[0].path.segments[0].name, "std");
        assert_eq!(program.imports[0].path.segments[1].name, "list");
        assert_eq!(program.declarations.len(), 1);
    }

    #[test]
    fn test_parse_import_alias() {
        let source = "import std/list as L";
        let program = Parser::parse_source(source).unwrap();
        assert_eq!(program.imports.len(), 1);
        assert!(program.imports[0].alias.is_some());
        assert_eq!(program.imports[0].alias.as_ref().unwrap().name, "L");
    }

    #[test]
    fn test_parse_import_selective() {
        let source = "import std/list.{map, filter, fold}";
        let program = Parser::parse_source(source).unwrap();
        assert_eq!(program.imports.len(), 1);
        assert!(program.imports[0].items.is_some());
        let items = program.imports[0].items.as_ref().unwrap();
        assert_eq!(items.len(), 3);
        assert_eq!(items[0].name, "map");
        assert_eq!(items[1].name, "filter");
        assert_eq!(items[2].name, "fold");
    }

    #[test]
    fn test_parse_pub_function() {
        let source = "pub fn add(a: Int, b: Int): Int = a + b";
        let program = Parser::parse_source(source).unwrap();
        assert_eq!(program.declarations.len(), 1);
        if let Declaration::Function(f) = &program.declarations[0] {
            assert_eq!(f.visibility, Visibility::Public);
        } else {
            panic!("Expected function declaration");
        }
    }

    #[test]
    fn test_parse_pub_let() {
        let source = "pub let x = 42";
        let program = Parser::parse_source(source).unwrap();
        assert_eq!(program.declarations.len(), 1);
        if let Declaration::Let(l) = &program.declarations[0] {
            assert_eq!(l.visibility, Visibility::Public);
        } else {
            panic!("Expected let declaration");
        }
    }

    #[test]
    fn test_parse_private_by_default() {
        let source = "fn foo(): Int = 42";
        let program = Parser::parse_source(source).unwrap();
        if let Declaration::Function(f) = &program.declarations[0] {
            assert_eq!(f.visibility, Visibility::Private);
        } else {
            panic!("Expected function declaration");
        }
    }

    // Schema Evolution tests

    #[test]
    fn test_parse_versioned_type() {
        let source = "type User @v1 { name: String, email: String }";
        let program = Parser::parse_source(source).unwrap();
        assert_eq!(program.declarations.len(), 1);
        if let Declaration::Type(t) = &program.declarations[0] {
            assert_eq!(t.name.name, "User");
            assert!(t.version.is_some());
            assert_eq!(t.version.unwrap().number, 1);
        } else {
            panic!("Expected type declaration");
        }
    }

    #[test]
    fn test_parse_versioned_type_v2() {
        let source = "type User @v2 { name: String, email: String, age: Int }";
        let program = Parser::parse_source(source).unwrap();
        if let Declaration::Type(t) = &program.declarations[0] {
            assert!(t.version.is_some());
            assert_eq!(t.version.unwrap().number, 2);
        } else {
            panic!("Expected type declaration");
        }
    }

    #[test]
    fn test_parse_versioned_type_expr() {
        let source = "let user: User @v2 = x";
        let program = Parser::parse_source(source).unwrap();
        if let Declaration::Let(l) = &program.declarations[0] {
            if let Some(TypeExpr::Versioned { base, constraint }) = &l.typ {
                if let TypeExpr::Named(name) = base.as_ref() {
                    assert_eq!(name.name, "User");
                } else {
                    panic!("Expected Named type");
                }
                if let VersionConstraint::Exact(v) = constraint {
                    assert_eq!(v.number, 2);
                } else {
                    panic!("Expected Exact version constraint");
                }
            } else {
                panic!("Expected Versioned type expression");
            }
        } else {
            panic!("Expected let declaration");
        }
    }

    #[test]
    fn test_parse_version_at_least() {
        let source = "let user: User @v2+ = x";
        let program = Parser::parse_source(source).unwrap();
        if let Declaration::Let(l) = &program.declarations[0] {
            if let Some(TypeExpr::Versioned { constraint, .. }) = &l.typ {
                if let VersionConstraint::AtLeast(v) = constraint {
                    assert_eq!(v.number, 2);
                } else {
                    panic!("Expected AtLeast version constraint");
                }
            } else {
                panic!("Expected Versioned type expression");
            }
        } else {
            panic!("Expected let declaration");
        }
    }

    #[test]
    fn test_parse_version_latest() {
        let source = "let user: User @latest = x";
        let program = Parser::parse_source(source).unwrap();
        if let Declaration::Let(l) = &program.declarations[0] {
            if let Some(TypeExpr::Versioned { constraint, .. }) = &l.typ {
                assert!(matches!(constraint, VersionConstraint::Latest(_)));
            } else {
                panic!("Expected Versioned type expression");
            }
        } else {
            panic!("Expected let declaration");
        }
    }

    #[test]
    fn test_parse_type_with_migration() {
        let source = r#"
            type User @v2 {
                name: String,
                email: String,
                age: Int,

                from @v1 = { name: old.name, email: old.email, age: 0 }
            }
        "#;
        let program = Parser::parse_source(source).unwrap();
        if let Declaration::Type(t) = &program.declarations[0] {
            assert_eq!(t.name.name, "User");
            assert_eq!(t.version.unwrap().number, 2);
            assert_eq!(t.migrations.len(), 1);
            assert_eq!(t.migrations[0].from_version.number, 1);
        } else {
            panic!("Expected type declaration");
        }
    }

    // ============ Behavioral Properties Tests ============

    #[test]
    fn test_parse_function_is_pure() {
        let source = "fn add(a: Int, b: Int): Int is pure = a + b";
        let program = Parser::parse_source(source).unwrap();
        if let Declaration::Function(f) = &program.declarations[0] {
            assert_eq!(f.name.name, "add");
            assert_eq!(f.properties.len(), 1);
            assert_eq!(f.properties[0], BehavioralProperty::Pure);
        } else {
            panic!("Expected function declaration");
        }
    }

    #[test]
    fn test_parse_function_multiple_properties() {
        let source = "fn double(x: Int): Int is pure, is total = x * 2";
        let program = Parser::parse_source(source).unwrap();
        if let Declaration::Function(f) = &program.declarations[0] {
            assert_eq!(f.name.name, "double");
            assert_eq!(f.properties.len(), 2);
            assert!(f.properties.contains(&BehavioralProperty::Pure));
            assert!(f.properties.contains(&BehavioralProperty::Total));
        } else {
            panic!("Expected function declaration");
        }
    }

    #[test]
    fn test_parse_function_with_effects_and_properties() {
        let source = "fn log(msg: String): Unit with {Logger} is deterministic = Logger.log(msg)";
        let program = Parser::parse_source(source).unwrap();
        if let Declaration::Function(f) = &program.declarations[0] {
            assert_eq!(f.name.name, "log");
            assert_eq!(f.effects.len(), 1);
            assert_eq!(f.effects[0].name, "Logger");
            assert_eq!(f.properties.len(), 1);
            assert_eq!(f.properties[0], BehavioralProperty::Deterministic);
        } else {
            panic!("Expected function declaration");
        }
    }

    #[test]
    fn test_parse_function_idempotent() {
        let source = "fn normalize(s: String): String is idempotent = s";
        let program = Parser::parse_source(source).unwrap();
        if let Declaration::Function(f) = &program.declarations[0] {
            assert_eq!(f.properties.len(), 1);
            assert_eq!(f.properties[0], BehavioralProperty::Idempotent);
        } else {
            panic!("Expected function declaration");
        }
    }

    #[test]
    fn test_parse_function_commutative() {
        let source = "fn add(a: Int, b: Int): Int is commutative = a + b";
        let program = Parser::parse_source(source).unwrap();
        if let Declaration::Function(f) = &program.declarations[0] {
            assert_eq!(f.properties.len(), 1);
            assert_eq!(f.properties[0], BehavioralProperty::Commutative);
        } else {
            panic!("Expected function declaration");
        }
    }

    #[test]
    fn test_parse_where_property_constraint() {
        let source = "fn retry(action: F): Int where F is idempotent = 0";
        let program = Parser::parse_source(source).unwrap();
        if let Declaration::Function(f) = &program.declarations[0] {
            assert_eq!(f.name.name, "retry");
            assert_eq!(f.where_clauses.len(), 1);
            if let WhereClause::PropertyConstraint {
                type_param,
                property,
                ..
            } = &f.where_clauses[0]
            {
                assert_eq!(type_param.name, "F");
                assert_eq!(*property, BehavioralProperty::Idempotent);
            } else {
                panic!("Expected PropertyConstraint");
            }
        } else {
            panic!("Expected function declaration");
        }
    }

    #[test]
    fn test_parse_where_result_refinement() {
        let source = "fn abs(x: Int): Int where result >= 0 = if x < 0 then 0 - x else x";
        let program = Parser::parse_source(source).unwrap();
        if let Declaration::Function(f) = &program.declarations[0] {
            assert_eq!(f.name.name, "abs");
            assert_eq!(f.where_clauses.len(), 1);
            if let WhereClause::ResultRefinement { predicate, .. } = &f.where_clauses[0] {
                // Check that the predicate is a binary comparison
                if let Expr::BinaryOp { op, .. } = predicate.as_ref() {
                    assert_eq!(*op, BinaryOp::Ge);
                } else {
                    panic!("Expected BinaryOp in refinement");
                }
            } else {
                panic!("Expected ResultRefinement");
            }
        } else {
            panic!("Expected function declaration");
        }
    }

    #[test]
    fn test_parse_all_behavioral_features() {
        // Single-line version to avoid newline issues
        let source = "fn process(f: F, x: Int): Int with {Logger} is pure, is total where F is deterministic = f(x)";
        let program = Parser::parse_source(source).unwrap();
        if let Declaration::Function(func) = &program.declarations[0] {
            assert_eq!(func.name.name, "process");
            assert_eq!(func.effects.len(), 1);
            assert_eq!(func.properties.len(), 2);
            assert!(func.properties.contains(&BehavioralProperty::Pure));
            assert!(func.properties.contains(&BehavioralProperty::Total));
            assert_eq!(func.where_clauses.len(), 1);
        } else {
            panic!("Expected function declaration");
        }
    }
}
