use super::*;

impl<'a> Parser<'a> {
    pub(super) fn parse_conditional(&mut self) -> Result<CompoundCommand> {
        self.ensure_double_bracket()?;
        let left_bracket_span = self.current_span;
        self.advance(); // consume '[['
        self.skip_conditional_newlines();

        let expression = self.parse_conditional_or(false)?;
        self.skip_conditional_newlines();

        let right_bracket_span = match self.current_token_kind {
            Some(TokenKind::DoubleRightBracket) => {
                let span = self.current_span;
                self.advance(); // consume ']]'
                span
            }
            None => {
                return Err(crate::error::Error::parse(
                    "unexpected end of input in [[ ]]".to_string(),
                ));
            }
            _ => return Err(self.error("expected ']]' to close conditional expression")),
        };

        Ok(CompoundCommand::Conditional(Box::new(ConditionalCommand {
            expression,
            span: left_bracket_span.merge(right_bracket_span),
            left_bracket_span,
            right_bracket_span,
        })))
    }

    pub(super) fn skip_conditional_newlines(&mut self) {
        while self.at(TokenKind::Newline) {
            self.advance();
        }
    }

    pub(super) fn parse_conditional_or(
        &mut self,
        stop_at_right_paren: bool,
    ) -> Result<ConditionalExpr> {
        let mut expr = self.parse_conditional_and(stop_at_right_paren)?;

        loop {
            self.skip_conditional_newlines();
            if !self.at(TokenKind::Or) {
                break;
            }

            let op_span = self.current_span;
            self.advance();
            let right = self.parse_conditional_and(stop_at_right_paren)?;
            expr = ConditionalExpr::Binary(ConditionalBinaryExpr {
                left: Box::new(expr),
                op: ConditionalBinaryOp::Or,
                op_span,
                right: Box::new(right),
            });
        }

        Ok(expr)
    }

    pub(super) fn parse_conditional_and(
        &mut self,
        stop_at_right_paren: bool,
    ) -> Result<ConditionalExpr> {
        let mut expr = self.parse_conditional_term(stop_at_right_paren)?;

        loop {
            self.skip_conditional_newlines();
            if !self.at(TokenKind::And) {
                break;
            }

            let op_span = self.current_span;
            self.advance();
            let right = self.parse_conditional_term(stop_at_right_paren)?;
            expr = ConditionalExpr::Binary(ConditionalBinaryExpr {
                left: Box::new(expr),
                op: ConditionalBinaryOp::And,
                op_span,
                right: Box::new(right),
            });
        }

        Ok(expr)
    }

    pub(super) fn parse_conditional_term(
        &mut self,
        stop_at_right_paren: bool,
    ) -> Result<ConditionalExpr> {
        self.skip_conditional_newlines();

        if let Some(op) = self.current_conditional_unary_op() {
            let op_span = self.current_span;
            self.advance();
            self.skip_conditional_newlines();

            let expr = if matches!(op, ConditionalUnaryOp::Not) {
                self.parse_conditional_term(stop_at_right_paren)?
            } else {
                if matches!(
                    op,
                    ConditionalUnaryOp::VariableSet | ConditionalUnaryOp::ReferenceVariable
                ) {
                    let word = self.collect_conditional_context_word(stop_at_right_paren)?;
                    self.conditional_var_ref_expr(word)
                } else {
                    let word = self.parse_conditional_operand_word(stop_at_right_paren)?;
                    ConditionalExpr::Word(word)
                }
            };

            return Ok(ConditionalExpr::Unary(ConditionalUnaryExpr {
                op,
                op_span,
                expr: Box::new(expr),
            }));
        }

        if self.at(TokenKind::DoubleLeftParen) {
            if self.dialect == ShellDialect::Zsh {
                let left_paren_span = self.current_span;
                if let Some(right_paren_span) = self.scan_arithmetic_command_close(left_paren_span)
                {
                    let span = left_paren_span.merge(right_paren_span);
                    let text = span.slice(self.input).to_string();
                    while self.current_token.is_some()
                        && self.current_span.start.offset() < right_paren_span.end.offset()
                    {
                        self.advance();
                    }
                    return Ok(ConditionalExpr::Word(
                        self.parse_word_with_context(&text, span, span.start, true),
                    ));
                }
            }
            self.split_current_double_left_paren();
        }

        let left = if self.at(TokenKind::LeftParen) {
            let left_paren_span = self.current_span;
            self.advance();
            let expr = self.parse_conditional_or(true)?;
            self.skip_conditional_newlines();
            if self.at(TokenKind::DoubleRightParen) {
                self.split_current_double_right_paren();
            }
            if !self.at(TokenKind::RightParen) {
                return Err(self.error("expected ')' in conditional expression"));
            }
            let right_paren_span = self.current_span;
            self.advance();
            ConditionalExpr::Parenthesized(ConditionalParenExpr {
                left_paren_span,
                expr: Box::new(expr),
                right_paren_span,
            })
        } else {
            ConditionalExpr::Word(self.parse_conditional_operand_word(stop_at_right_paren)?)
        };

        self.skip_conditional_newlines();

        let Some(op) = self.current_conditional_comparison_op() else {
            return Ok(left);
        };

        let op_span = self.current_span;
        self.advance();
        self.skip_conditional_newlines();

        let right = match op {
            ConditionalBinaryOp::RegexMatch => {
                if self.at(TokenKind::LeftBrace) {
                    return Err(self.error("expected conditional operand"));
                }
                ConditionalExpr::Regex(self.collect_conditional_context_word(stop_at_right_paren)?)
            }
            ConditionalBinaryOp::PatternEqShort
            | ConditionalBinaryOp::PatternEq
            | ConditionalBinaryOp::PatternNe => {
                let word = self.collect_conditional_context_word(stop_at_right_paren)?;
                ConditionalExpr::Pattern(self.pattern_from_conditional_word(&word))
            }
            _ => ConditionalExpr::Word(self.parse_conditional_operand_word(stop_at_right_paren)?),
        };

        Ok(ConditionalExpr::Binary(ConditionalBinaryExpr {
            left: Box::new(left),
            op,
            op_span,
            right: Box::new(right),
        }))
    }

    pub(super) fn parse_conditional_operand_word(
        &mut self,
        stop_at_right_paren: bool,
    ) -> Result<Word> {
        self.skip_conditional_newlines();

        if let Some(word) = self.current_conditional_source_word(stop_at_right_paren) {
            self.advance_past_word(&word);
            self.restore_conditional_source_delimiter(word.span.end, stop_at_right_paren);
            return Ok(word);
        }

        if let Some(word) = self.take_current_word_and_advance() {
            return Ok(word);
        }

        let Some(word) = self.current_conditional_literal_word() else {
            return Err(self.error("expected conditional operand"));
        };
        self.advance_past_word(&word);
        Ok(word)
    }

    pub(super) fn conditional_var_ref_expr(&self, word: Word) -> ConditionalExpr {
        self.parse_var_ref_from_word(&word, SubscriptInterpretation::Contextual)
            .map(Box::new)
            .map(ConditionalExpr::VarRef)
            .unwrap_or(ConditionalExpr::Word(word))
    }

    pub(super) fn current_conditional_source_word(
        &mut self,
        stop_at_right_paren: bool,
    ) -> Option<Word> {
        let token = self.current_token.as_ref()?;
        if token.flags.is_synthetic() {
            return None;
        }

        if matches!(
            self.current_token_kind,
            Some(TokenKind::QuotedWord | TokenKind::LiteralWord)
        ) {
            return None;
        }

        let starts_with_paren = matches!(self.current_token_kind, Some(TokenKind::LeftParen));
        let starts_with_zsh_pattern_punct = matches!(
            self.current_token_kind,
            Some(TokenKind::RedirectIn | TokenKind::RedirectOut | TokenKind::RedirectReadWrite)
        ) && self.dialect == ShellDialect::Zsh;

        if !starts_with_paren
            && !starts_with_zsh_pattern_punct
            && !self.current_token_kind.is_some_and(TokenKind::is_word_like)
        {
            return None;
        }

        let start = self.current_span.start;
        let (text, end) =
            self.scan_conditional_source_word(start, stop_at_right_paren, starts_with_paren)?;
        let span = Span::from_positions(start, end);
        Some(self.parse_word_with_context(&text, span, start, true))
    }

    pub(super) fn scan_conditional_source_word(
        &self,
        start: Position,
        stop_at_right_paren: bool,
        starts_with_paren: bool,
    ) -> Option<(String, Position)> {
        if start.offset() >= self.input.len() {
            return None;
        }

        let mut cursor = start;
        let mut text = String::new();
        let mut paren_depth = 0_i32;
        let mut brace_depth = 0_i32;
        let mut bracket_depth = 0_i32;
        let mut in_single = false;
        let mut in_double = false;
        let mut in_backtick = false;
        let mut escaped = false;
        let mut prev_char = None;

        while cursor.offset() < self.input.len() {
            let rest = &self.input[cursor.offset()..];
            if !in_single
                && !in_double
                && !in_backtick
                && !escaped
                && paren_depth == 0
                && brace_depth == 0
                && bracket_depth == 0
            {
                if rest.starts_with("]]")
                    || rest.starts_with("&&")
                    || rest.starts_with("||")
                    || (!starts_with_paren && rest.starts_with(')'))
                    || (stop_at_right_paren && rest.starts_with(')'))
                {
                    break;
                }

                let ch = rest.chars().next()?;
                if matches!(ch, ' ' | '\t' | '\n' | ';') {
                    break;
                }
            }

            let ch = self.input[cursor.offset()..].chars().next()?;
            cursor.advance(ch);
            text.push(ch);

            if escaped {
                escaped = false;
                prev_char = Some(ch);
                continue;
            }

            match ch {
                '\\' if !in_single => escaped = true,
                '\'' if !in_double => in_single = !in_single,
                '"' if !in_single => in_double = !in_double,
                '`' if !in_single => in_backtick = !in_backtick,
                '(' if !in_single && !in_double && brace_depth == 0 => paren_depth += 1,
                ')' if !in_single && !in_double && brace_depth == 0 && paren_depth > 0 => {
                    paren_depth -= 1
                }
                '{' if !in_single && !in_double && (brace_depth > 0 || prev_char == Some('$')) => {
                    brace_depth += 1
                }
                '}' if !in_single && !in_double && brace_depth > 0 => brace_depth -= 1,
                '[' if !in_single && !in_double => bracket_depth += 1,
                ']' if !in_single && !in_double && bracket_depth > 0 => bracket_depth -= 1,
                _ => {}
            }

            prev_char = Some(ch);
        }

        (!text.is_empty()).then_some((text, cursor))
    }

    pub(super) fn conditional_source_delimiter_after(
        &self,
        end: Position,
        stop_at_right_paren: bool,
    ) -> Option<(TokenKind, Span)> {
        let mut cursor = end;
        while cursor.offset() < self.input.len() {
            let rest = &self.input[cursor.offset()..];
            let ch = rest.chars().next()?;
            if matches!(ch, ' ' | '\t') {
                cursor.advance(ch);
                continue;
            }
            break;
        }

        let rest = self.input.get(cursor.offset()..)?;
        let (kind, text) = if rest.starts_with("]]") {
            (TokenKind::DoubleRightBracket, "]]")
        } else if rest.starts_with("&&") {
            (TokenKind::And, "&&")
        } else if rest.starts_with("||") {
            (TokenKind::Or, "||")
        } else if stop_at_right_paren && rest.starts_with("))") {
            (TokenKind::DoubleRightParen, "))")
        } else if stop_at_right_paren && rest.starts_with(')') {
            (TokenKind::RightParen, ")")
        } else {
            return None;
        };

        Some((kind, Span::from_positions(cursor, cursor.advanced_by(text))))
    }

    pub(super) fn restore_conditional_source_delimiter(
        &mut self,
        end: Position,
        stop_at_right_paren: bool,
    ) {
        let Some((kind, span)) = self.conditional_source_delimiter_after(end, stop_at_right_paren)
        else {
            return;
        };

        if self.current_token_kind == Some(kind) && self.current_span == span {
            return;
        }

        if let Some(current_kind) = self.current_token_kind
            && matches!(
                current_kind,
                TokenKind::Newline
                    | TokenKind::Semicolon
                    | TokenKind::And
                    | TokenKind::Or
                    | TokenKind::RightParen
                    | TokenKind::DoubleRightBracket
            )
        {
            self.synthetic_tokens
                .push_front(SyntheticToken::punctuation(current_kind, self.current_span));
        }

        self.set_current_kind(kind, span);
    }

    pub(super) fn current_conditional_unary_op(&self) -> Option<ConditionalUnaryOp> {
        if !self.at(TokenKind::Word) {
            return None;
        }
        let word = self.current_word_str()?;

        Some(match word {
            "!" => ConditionalUnaryOp::Not,
            "-e" | "-a" => ConditionalUnaryOp::Exists,
            "-f" => ConditionalUnaryOp::RegularFile,
            "-d" => ConditionalUnaryOp::Directory,
            "-c" => ConditionalUnaryOp::CharacterSpecial,
            "-b" => ConditionalUnaryOp::BlockSpecial,
            "-p" => ConditionalUnaryOp::NamedPipe,
            "-S" => ConditionalUnaryOp::Socket,
            "-L" | "-h" => ConditionalUnaryOp::Symlink,
            "-k" => ConditionalUnaryOp::Sticky,
            "-g" => ConditionalUnaryOp::SetGroupId,
            "-u" => ConditionalUnaryOp::SetUserId,
            "-G" => ConditionalUnaryOp::GroupOwned,
            "-O" => ConditionalUnaryOp::UserOwned,
            "-N" => ConditionalUnaryOp::Modified,
            "-r" => ConditionalUnaryOp::Readable,
            "-w" => ConditionalUnaryOp::Writable,
            "-x" => ConditionalUnaryOp::Executable,
            "-s" => ConditionalUnaryOp::NonEmptyFile,
            "-t" => ConditionalUnaryOp::FdTerminal,
            "-z" => ConditionalUnaryOp::EmptyString,
            "-n" => ConditionalUnaryOp::NonEmptyString,
            "-o" => ConditionalUnaryOp::OptionSet,
            "-v" => ConditionalUnaryOp::VariableSet,
            "-R" => ConditionalUnaryOp::ReferenceVariable,
            _ => return None,
        })
    }

    pub(super) fn current_conditional_comparison_op(&self) -> Option<ConditionalBinaryOp> {
        match self.current_token_kind? {
            TokenKind::Word => Some(match self.current_word_str()? {
                "=" => ConditionalBinaryOp::PatternEqShort,
                "==" => ConditionalBinaryOp::PatternEq,
                "!=" => ConditionalBinaryOp::PatternNe,
                "=~" => ConditionalBinaryOp::RegexMatch,
                "-nt" => ConditionalBinaryOp::NewerThan,
                "-ot" => ConditionalBinaryOp::OlderThan,
                "-ef" => ConditionalBinaryOp::SameFile,
                "-eq" => ConditionalBinaryOp::ArithmeticEq,
                "-ne" => ConditionalBinaryOp::ArithmeticNe,
                "-le" => ConditionalBinaryOp::ArithmeticLe,
                "-ge" => ConditionalBinaryOp::ArithmeticGe,
                "-lt" => ConditionalBinaryOp::ArithmeticLt,
                "-gt" => ConditionalBinaryOp::ArithmeticGt,
                _ => return None,
            }),
            TokenKind::RedirectIn => Some(ConditionalBinaryOp::LexicalBefore),
            TokenKind::RedirectOut => Some(ConditionalBinaryOp::LexicalAfter),
            _ => None,
        }
    }

    pub(super) fn collect_conditional_context_word(
        &mut self,
        stop_at_right_paren: bool,
    ) -> Result<Word> {
        self.skip_conditional_newlines();

        if let Some(word) = self.current_conditional_source_word(stop_at_right_paren) {
            self.advance_past_word(&word);
            self.restore_conditional_source_delimiter(word.span.end, stop_at_right_paren);
            return Ok(word);
        }

        let mut first_word: Option<Word> = None;
        let mut parts = Vec::new();
        let mut start = None;
        let mut end = None;
        let mut previous_end: Option<Position> = None;
        let mut composite = false;
        let mut paren_depth = 0usize;

        loop {
            self.skip_conditional_newlines();

            match self.current_token_kind {
                Some(TokenKind::DoubleRightBracket) => break,
                Some(TokenKind::And) | Some(TokenKind::Or) if paren_depth == 0 => break,
                Some(TokenKind::RightParen) if stop_at_right_paren && paren_depth == 0 => break,
                Some(TokenKind::DoubleRightParen) if stop_at_right_paren && paren_depth == 0 => {
                    break;
                }
                None => break,
                _ => {}
            }

            if let Some(prev_end) = previous_end
                && prev_end.offset() < self.current_span.start.offset()
            {
                let gap_span = Span::from_positions(prev_end, self.current_span.start);
                let gap_text = gap_span.slice(self.input);
                if let Some(word) = first_word.take() {
                    parts.extend(word.parts);
                }
                if Self::source_text_needs_quote_preserving_decode(gap_text) {
                    let gap_word = self.decode_word_text_preserving_quotes_if_needed(
                        gap_text,
                        gap_span,
                        gap_span.start,
                        true,
                    );
                    parts.extend(gap_word.parts);
                } else {
                    parts.push(WordPartNode::new(
                        WordPart::Literal(LiteralText::source()),
                        gap_span,
                    ));
                }
                composite = true;
            }

            match self.current_token_kind {
                Some(TokenKind::Word | TokenKind::LiteralWord | TokenKind::QuotedWord) => {
                    let word = self
                        .take_current_word()
                        .ok_or_else(|| self.error("expected conditional operand"))?;
                    if start.is_none() {
                        start = Some(word.span.start);
                    } else {
                        if let Some(first) = first_word.take() {
                            parts.extend(first.parts);
                        }
                        composite = true;
                    }
                    end = Some(word.span.end);
                    if first_word.is_none() && !composite {
                        first_word = Some(word);
                    } else {
                        parts.extend(word.parts);
                    }
                    previous_end = Some(self.current_span.end);
                    self.advance();
                }
                Some(TokenKind::LeftParen) => {
                    if start.is_none() {
                        start = Some(self.current_span.start);
                    }
                    end = Some(self.current_span.end);
                    if let Some(word) = first_word.take() {
                        parts.extend(word.parts);
                    }
                    parts.push(WordPartNode::new(
                        WordPart::Literal(LiteralText::owned("(")),
                        self.current_span,
                    ));
                    previous_end = Some(self.current_span.end);
                    paren_depth += 1;
                    composite = true;
                    self.advance();
                }
                Some(TokenKind::DoubleLeftParen) => {
                    if start.is_none() {
                        start = Some(self.current_span.start);
                    }
                    end = Some(self.current_span.end);
                    if let Some(word) = first_word.take() {
                        parts.extend(word.parts);
                    }
                    parts.push(WordPartNode::new(
                        WordPart::Literal(LiteralText::owned("((")),
                        self.current_span,
                    ));
                    previous_end = Some(self.current_span.end);
                    paren_depth += 2;
                    composite = true;
                    self.advance();
                }
                Some(TokenKind::RightParen) => {
                    if paren_depth == 0 {
                        break;
                    }
                    if start.is_none() {
                        start = Some(self.current_span.start);
                    }
                    end = Some(self.current_span.end);
                    if let Some(word) = first_word.take() {
                        parts.extend(word.parts);
                    }
                    parts.push(WordPartNode::new(
                        WordPart::Literal(LiteralText::owned(")")),
                        self.current_span,
                    ));
                    previous_end = Some(self.current_span.end);
                    paren_depth = paren_depth.saturating_sub(1);
                    composite = true;
                    self.advance();
                }
                Some(TokenKind::DoubleRightParen) => {
                    if start.is_none() {
                        start = Some(self.current_span.start);
                    }
                    end = Some(self.current_span.end);
                    if let Some(word) = first_word.take() {
                        parts.extend(word.parts);
                    }
                    parts.push(WordPartNode::new(
                        WordPart::Literal(LiteralText::owned("))")),
                        self.current_span,
                    ));
                    previous_end = Some(self.current_span.end);
                    paren_depth = paren_depth.saturating_sub(2);
                    composite = true;
                    self.advance();
                }
                Some(TokenKind::Pipe) => {
                    if start.is_none() {
                        start = Some(self.current_span.start);
                    }
                    end = Some(self.current_span.end);
                    if let Some(word) = first_word.take() {
                        parts.extend(word.parts);
                    }
                    parts.push(WordPartNode::new(
                        WordPart::Literal(LiteralText::owned("|")),
                        self.current_span,
                    ));
                    previous_end = Some(self.current_span.end);
                    composite = true;
                    self.advance();
                }
                Some(TokenKind::And) => {
                    if paren_depth == 0 {
                        break;
                    }
                    if start.is_none() {
                        start = Some(self.current_span.start);
                    }
                    end = Some(self.current_span.end);
                    if let Some(word) = first_word.take() {
                        parts.extend(word.parts);
                    }
                    parts.push(WordPartNode::new(
                        WordPart::Literal(LiteralText::owned("&&")),
                        self.current_span,
                    ));
                    previous_end = Some(self.current_span.end);
                    composite = true;
                    self.advance();
                }
                Some(TokenKind::Or) => {
                    if paren_depth == 0 {
                        break;
                    }
                    if start.is_none() {
                        start = Some(self.current_span.start);
                    }
                    end = Some(self.current_span.end);
                    if let Some(word) = first_word.take() {
                        parts.extend(word.parts);
                    }
                    parts.push(WordPartNode::new(
                        WordPart::Literal(LiteralText::owned("||")),
                        self.current_span,
                    ));
                    previous_end = Some(self.current_span.end);
                    composite = true;
                    self.advance();
                }
                Some(TokenKind::RedirectIn)
                | Some(TokenKind::RedirectOut)
                | Some(TokenKind::RedirectReadWrite) => {
                    let literal = self.input
                        [self.current_span.start.offset()..self.current_span.end.offset()]
                        .to_string();
                    if start.is_none() {
                        start = Some(self.current_span.start);
                    }
                    end = Some(self.current_span.end);
                    if let Some(word) = first_word.take() {
                        parts.extend(word.parts);
                    }
                    parts.push(WordPartNode::new(
                        WordPart::Literal(self.literal_text(
                            literal,
                            self.current_span.start,
                            self.current_span.end,
                            true,
                        )),
                        self.current_span,
                    ));
                    previous_end = Some(self.current_span.end);
                    composite = true;
                    self.advance();
                }
                _ => {
                    let literal = self.input
                        [self.current_span.start.offset()..self.current_span.end.offset()]
                        .to_string();
                    if literal.is_empty() {
                        break;
                    }
                    if start.is_none() {
                        start = Some(self.current_span.start);
                    }
                    end = Some(self.current_span.end);
                    if let Some(word) = first_word.take() {
                        parts.extend(word.parts);
                    }
                    parts.push(WordPartNode::new(
                        WordPart::Literal(self.literal_text(
                            literal,
                            self.current_span.start,
                            self.current_span.end,
                            true,
                        )),
                        self.current_span,
                    ));
                    previous_end = Some(self.current_span.end);
                    composite = true;
                    self.advance();
                }
            }
        }

        if !composite && let Some(word) = first_word {
            return Ok(word);
        }

        let (start, end) = match (start, end) {
            (Some(start), Some(end)) => (start, end),
            _ => return Err(self.error("expected conditional operand")),
        };

        Ok(self.word_with_parts(parts, Span::from_positions(start, end)))
    }

    pub(super) fn parse_arithmetic_command(&mut self) -> Result<CompoundCommand> {
        self.ensure_arithmetic_command()?;
        let left_paren_span = self.current_span;
        let Some(right_paren_span) = self.scan_arithmetic_command_close(left_paren_span) else {
            return Err(Error::parse(
                "unexpected end of input in arithmetic command".to_string(),
            ));
        };
        while self.current_token.is_some()
            && self.current_span.start.offset() < right_paren_span.end.offset()
        {
            self.advance();
        }

        let expr_span = Self::optional_span(left_paren_span.end, right_paren_span.start);
        let expr_ast = self
            .parse_explicit_arithmetic_span(expr_span, "invalid arithmetic command")
            .ok()
            .flatten();
        Ok(CompoundCommand::Arithmetic(Box::new(ArithmeticCommand {
            span: left_paren_span.merge(right_paren_span),
            left_paren_span,
            expr_span,
            expr_ast,
            right_paren_span,
        })))
    }

    pub(super) fn scan_arithmetic_command_close(&self, left_paren_span: Span) -> Option<Span> {
        let mut cursor = left_paren_span.end;
        let mut depth = 0_i32;
        let mut in_single = false;
        let mut in_double = false;
        let mut in_backtick = false;
        let mut escaped = false;

        while cursor.offset() < self.input.len() {
            let rest = &self.input[cursor.offset()..];

            if !in_single && !in_double && !in_backtick {
                if rest.starts_with("((") {
                    depth += 2;
                    cursor = cursor.advanced_by("((");
                    continue;
                }

                if rest.starts_with("))") {
                    if depth == 0 {
                        return Some(Span::from_positions(cursor, cursor.advanced_by("))")));
                    }
                    if depth == 1 {
                        cursor.advance(')');
                        return Some(Span::from_positions(cursor, cursor.advanced_by("))")));
                    }
                    depth -= 2;
                    cursor = cursor.advanced_by("))");
                    continue;
                }
            }

            let ch = rest.chars().next()?;
            cursor.advance(ch);

            if escaped {
                escaped = false;
                continue;
            }

            match ch {
                '\\' if !in_single => escaped = true,
                '\'' if !in_double && !in_backtick => in_single = !in_single,
                '"' if !in_single && !in_backtick => in_double = !in_double,
                '`' if !in_single && !in_double => in_backtick = !in_backtick,
                '(' if !in_single && !in_double && !in_backtick => depth += 1,
                ')' if !in_single && !in_double && !in_backtick && depth > 0 => depth -= 1,
                _ => {}
            }
        }

        None
    }
}
