use super::quoted_text::QuotedText;

/// Enhanced tokenizer that handles key=value pairs properly and preserves quote information  
#[allow(dead_code)]
pub fn tokenize_arguments(input: &str) -> Vec<QuotedText> {
    let mut tokens = Vec::new();
    let mut chars = input.chars().peekable();

    // Skip leading whitespace
    while chars.peek() == Some(&' ') || chars.peek() == Some(&'\t') {
        chars.next();
    }

    while chars.peek().is_some() {
        let mut token_content = String::new();
        let mut was_quoted = false;
        let mut in_quotes = false;
        let mut _eq_found = false;

        // Read the token, which might be key=value or just a value
        while let Some(&ch) = chars.peek() {
            if (ch == ' ' || ch == '\t') && !in_quotes {
                break; // End of token
            }

            let current_char = chars.next().unwrap();

            if current_char == '"' {
                if in_quotes {
                    // Closing quote
                    in_quotes = false;
                    if token_content.is_empty() {
                        // This was an empty quoted string
                        was_quoted = true;
                    }
                } else {
                    // Opening quote
                    in_quotes = true;
                    if token_content.is_empty() {
                        // Quote at beginning means this whole token is quoted
                        was_quoted = true;
                    }
                    // Don't include the quote character in content unless it's escaped
                }
            } else if current_char == '\\' && in_quotes {
                // Handle escape sequences
                if let Some(next_ch) = chars.next() {
                    match next_ch {
                        '"' => token_content.push('"'),
                        '\\' => token_content.push('\\'),
                        _ => {
                            token_content.push('\\');
                            token_content.push(next_ch);
                        }
                    }
                } else {
                    token_content.push('\\');
                }
            } else if current_char == '=' && !in_quotes {
                _eq_found = true;
                token_content.push(current_char);
            } else {
                token_content.push(current_char);
            }
        }

        if !token_content.is_empty() || was_quoted {
            tokens.push(if was_quoted {
                QuotedText::quoted(token_content)
            } else {
                QuotedText::unquoted(token_content)
            });
        }

        // Skip trailing whitespace
        while chars.peek() == Some(&' ') || chars.peek() == Some(&'\t') {
            chars.next();
        }
    }

    tokens
}

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

    #[test]
    fn test_simple_unquoted_tokens() {
        let tokens = tokenize_arguments("arg1 arg2 arg3");
        assert_eq!(tokens.len(), 3);

        assert_eq!(tokens[0].content, "arg1");
        assert!(!tokens[0].was_quoted);

        assert_eq!(tokens[1].content, "arg2");
        assert!(!tokens[1].was_quoted);

        assert_eq!(tokens[2].content, "arg3");
        assert!(!tokens[2].was_quoted);
    }

    #[test]
    fn test_simple_quoted_tokens() {
        let tokens = tokenize_arguments("\"arg1\" \"arg2\"");
        assert_eq!(tokens.len(), 2);

        assert_eq!(tokens[0].content, "arg1");
        assert!(tokens[0].was_quoted);

        assert_eq!(tokens[1].content, "arg2");
        assert!(tokens[1].was_quoted);
    }

    #[test]
    fn test_mixed_quoted_unquoted() {
        let tokens = tokenize_arguments("arg1 \"quoted arg\" arg3");
        assert_eq!(tokens.len(), 3);

        assert_eq!(tokens[0].content, "arg1");
        assert!(!tokens[0].was_quoted);

        assert_eq!(tokens[1].content, "quoted arg");
        assert!(tokens[1].was_quoted);

        assert_eq!(tokens[2].content, "arg3");
        assert!(!tokens[2].was_quoted);
    }

    #[test]
    fn test_escaped_quotes() {
        let tokens = tokenize_arguments("\"quote\\\"test\"");
        assert_eq!(tokens.len(), 1);

        assert_eq!(tokens[0].content, "quote\"test");
        assert!(tokens[0].was_quoted);
    }

    #[test]
    fn test_escaped_backslashes() {
        let tokens = tokenize_arguments("\"back\\\\slash\"");
        assert_eq!(tokens.len(), 1);

        assert_eq!(tokens[0].content, "back\\slash");
        assert!(tokens[0].was_quoted);
    }

    #[test]
    fn test_key_value_pairs() {
        let tokens = tokenize_arguments("key=value");
        assert_eq!(tokens.len(), 1);

        assert_eq!(tokens[0].content, "key=value");
        assert!(!tokens[0].was_quoted);
    }

    #[test]
    fn test_key_value_with_quoted_value() {
        let tokens = tokenize_arguments("key=\"value with spaces\"");
        assert_eq!(tokens.len(), 1);

        assert_eq!(tokens[0].content, "key=value with spaces");
        assert!(!tokens[0].was_quoted); // The whole token is not quoted, just the value part
    }

    #[test]
    fn test_quoted_key_value() {
        let tokens = tokenize_arguments("\"key with spaces\"=value");
        assert_eq!(tokens.len(), 1);

        assert_eq!(tokens[0].content, "key with spaces=value");
        assert!(tokens[0].was_quoted); // Token starts with quote, so it's marked as quoted
    }

    #[test]
    fn test_empty_string() {
        let tokens = tokenize_arguments("");
        assert_eq!(tokens.len(), 0);
    }

    #[test]
    fn test_whitespace_only() {
        let tokens = tokenize_arguments("   \t  ");
        assert_eq!(tokens.len(), 0);
    }

    #[test]
    fn test_empty_quoted_string() {
        let tokens = tokenize_arguments("\"\"");
        assert_eq!(tokens.len(), 1);

        assert_eq!(tokens[0].content, "");
        assert!(tokens[0].was_quoted);
    }

    #[test]
    fn test_multiple_empty_quotes() {
        let tokens = tokenize_arguments("\"\" \"\"");
        assert_eq!(tokens.len(), 2);

        assert_eq!(tokens[0].content, "");
        assert!(tokens[0].was_quoted);

        assert_eq!(tokens[1].content, "");
        assert!(tokens[1].was_quoted);
    }

    #[test]
    fn test_mixed_content_quotes() {
        let tokens = tokenize_arguments("arg1=\"quoted value\" arg2=unquoted");
        assert_eq!(tokens.len(), 2);

        assert_eq!(tokens[0].content, "arg1=quoted value");
        assert!(!tokens[0].was_quoted);

        assert_eq!(tokens[1].content, "arg2=unquoted");
        assert!(!tokens[1].was_quoted);
    }

    #[test]
    fn test_quote_in_middle_of_token() {
        let tokens = tokenize_arguments("test\"quote");
        assert_eq!(tokens.len(), 1);

        assert_eq!(tokens[0].content, "testquote");
        assert!(!tokens[0].was_quoted);
    }

    #[test]
    fn test_unclosed_quotes() {
        let tokens = tokenize_arguments("\"unclosed");
        assert_eq!(tokens.len(), 1);

        assert_eq!(tokens[0].content, "unclosed");
        assert!(tokens[0].was_quoted); // Started with quote, so marked as quoted
    }

    #[test]
    fn test_tabs_and_spaces() {
        let tokens = tokenize_arguments("arg1\t\targ2\t arg3");
        assert_eq!(tokens.len(), 3);

        assert_eq!(tokens[0].content, "arg1");
        assert_eq!(tokens[1].content, "arg2");
        assert_eq!(tokens[2].content, "arg3");
    }

    #[test]
    fn test_leading_and_trailing_whitespace() {
        let tokens = tokenize_arguments("  arg1   arg2  ");
        assert_eq!(tokens.len(), 2);

        assert_eq!(tokens[0].content, "arg1");
        assert_eq!(tokens[1].content, "arg2");
    }

    #[test]
    fn test_complex_key_value() {
        let tokens = tokenize_arguments("class=\"main container\" id=header data=\"test value\"");
        assert_eq!(tokens.len(), 3);

        assert_eq!(tokens[0].content, "class=main container");
        assert!(!tokens[0].was_quoted);

        assert_eq!(tokens[1].content, "id=header");
        assert!(!tokens[1].was_quoted);

        assert_eq!(tokens[2].content, "data=test value");
        assert!(!tokens[2].was_quoted);
    }

    #[test]
    fn test_equals_without_value() {
        let tokens = tokenize_arguments("key=");
        assert_eq!(tokens.len(), 1);

        assert_eq!(tokens[0].content, "key=");
        assert!(!tokens[0].was_quoted);
    }

    #[test]
    fn test_equals_without_key() {
        let tokens = tokenize_arguments("=value");
        assert_eq!(tokens.len(), 1);

        assert_eq!(tokens[0].content, "=value");
        assert!(!tokens[0].was_quoted);
    }

    #[test]
    fn test_multiple_equals() {
        let tokens = tokenize_arguments("key=value=extra");
        assert_eq!(tokens.len(), 1);

        assert_eq!(tokens[0].content, "key=value=extra");
        assert!(!tokens[0].was_quoted);
    }

    #[test]
    fn test_special_characters() {
        let tokens = tokenize_arguments("key=@#$%^&*()");
        assert_eq!(tokens.len(), 1);

        assert_eq!(tokens[0].content, "key=@#$%^&*()");
        assert!(!tokens[0].was_quoted);
    }

    #[test]
    fn test_unicode_content() {
        let tokens = tokenize_arguments("ключ=значение");
        assert_eq!(tokens.len(), 1);

        assert_eq!(tokens[0].content, "ключ=значение");
        assert!(!tokens[0].was_quoted);
    }

    #[test]
    fn test_quoted_unicode() {
        let tokens = tokenize_arguments("\"ключ с пробелами\"=значение");
        assert_eq!(tokens.len(), 1);

        assert_eq!(tokens[0].content, "ключ с пробелами=значение");
        assert!(tokens[0].was_quoted); // Token starts with quote, so it's marked as quoted
    }

    #[test]
    fn test_escape_sequences_outside_quotes() {
        let tokens = tokenize_arguments("test\\\"value");
        assert_eq!(tokens.len(), 1);

        // The actual behavior: quote in middle causes quote processing
        assert_eq!(tokens[0].content, "test\\value");
        assert!(!tokens[0].was_quoted);
    }
}
