use std::fs;
use std::path::Path;
use std::collections::HashSet;

/// Extract translations from source files for build script usage
pub fn extract_translations_from_source(source_dir: &str) -> HashSet<(String, (String, bool, String))> {
    let mut translations = HashSet::new();
    walk_rust_files(source_dir, &mut translations);
    translations
}

/// Generate code for translation keys
pub fn generate_translation_keys_code(translations: &HashSet<(String, (String, bool, String))>) -> String {
    let mut code = String::from("// Auto-generated translation keys\n\n");
    code.push_str("pub fn get_all_translation_keys() -> Vec<(String, rust_shared::i18n::Uniq, rust_shared::i18n::Language)> {\n");
    code.push_str("    vec![\n");
    
    for (text, (identifier, is_manual, text_language)) in translations {
        let uniq_variant = if *is_manual {
            format!("rust_shared::i18n::Uniq::Manual(\"{}\")", identifier.replace("\"", "\\\""))
        } else {
            format!("rust_shared::i18n::Uniq::Module(\"{}\")", identifier.replace("\"", "\\\""))
        };
        
        code.push_str(&format!("        (indoc::indoc!(\"{}\").to_string(), {}, rust_shared::i18n::Language::{}),\n", 
                              text.replace("\"", "\\\""), 
                              uniq_variant,
                              text_language));
    }
    
    code.push_str("    ]\n");
    code.push_str("}\n");
    code
}

fn walk_rust_files(dir: &str, translations: &mut HashSet<(String, (String, bool, String))>) {
    if let Ok(entries) = fs::read_dir(dir) {
        for entry in entries.flatten() {
            let path = entry.path();
            if path.is_dir() {
                walk_rust_files(path.to_str().unwrap(), translations);
            } else if path.extension().is_some_and(|ext| ext == "rs") {
                extract_translations_from_file(&path, translations);
            }
        }
    }
}

fn extract_translations_from_file(path: &Path, translations: &mut HashSet<(String, (String, bool, String))>) {
    if let Ok(content) = fs::read_to_string(path) {
        let mut module = path.to_str()
            .unwrap()
            .replace("src/", "")
            .replace(".rs", "")
            .replace("/", "::");
        
        if module.ends_with("::mod") {
            module = module.replace("::mod", "");
        }
            
        let chars: Vec<char> = content.chars().collect();
        let mut i = 0;
        
        while i < chars.len() {
            if i + 4 < chars.len() && 
               chars[i] == 't' && chars[i+1] == '8' && 
               (chars[i+2] == 'x' || chars[i+2] == 'r' || chars[i+2] == 's') && chars[i+3] == '!' {
                
                let macro_type = chars[i+2]; // 'x' for t8x!, 'r' for t8r!
                
                i += 4;
                while i < chars.len() && chars[i].is_whitespace() {
                    i += 1;
                }
                
                if i < chars.len() && chars[i] == '(' {
                    i += 1;
                    
                    let mut paren_count = 1;
                    let mut in_string = false;
                    let mut string_delimiter = '"';
                    let mut escape_next = false;
                    let mut current_token = String::new();
                    let mut args = Vec::new();
                    let mut arg_is_string = false;
                    
                    while i < chars.len() && paren_count > 0 {
                        let ch = chars[i];
                        
                        if escape_next {
                            if in_string {
                                current_token.push(ch);
                            }
                            escape_next = false;
                        } else if ch == '\\' && in_string {
                            escape_next = true;
                            current_token.push(ch);
                        } else if !in_string && (ch == '"' || ch == '\'') {
                            in_string = true;
                            string_delimiter = ch;
                            current_token.clear(); // Start fresh for string content
                            arg_is_string = true;
                        } else if in_string && ch == string_delimiter {
                            in_string = false;
                            args.push((current_token.clone(), arg_is_string));
                            current_token.clear();
                            arg_is_string = false;
                        } else if in_string {
                            current_token.push(ch);
                        } else if ch == ',' && paren_count == 1 {
                            if !current_token.trim().is_empty() {
                                args.push((current_token.trim().to_string(), arg_is_string));
                            }
                            current_token.clear();
                            arg_is_string = false;
                        } else if ch == '(' {
                            paren_count += 1;
                            if !in_string {
                                current_token.push(ch);
                            }
                        } else if ch == ')' {
                            paren_count -= 1;
                            if paren_count == 0 {
                                if !current_token.trim().is_empty() {
                                    args.push((current_token.trim().to_string(), arg_is_string));
                                }
                            } else if !in_string {
                                current_token.push(ch);
                            }
                        } else if !in_string {
                            current_token.push(ch);
                        }
                        
                        i += 1;
                    }
                    
                    let mut text = String::new();
                    let mut unique_id = String::new();
                    let mut text_language = String::from("En"); // Default to English
                    
                    if macro_type == 'x' {
                        // 4 args: ($text_language:expr, $text:literal, $language:expr, $uniq:literal)
                        // 3 args: ($text:literal, $language:expr, $uniq:literal) OR ($text_language:expr, $text:literal, $language:expr)
                        // 2 args: ($text:literal, $language:expr)
                        
                        match args.len() {
                            4 => {
                                // ($text_language:expr, $text:literal, $language:expr, $uniq:literal)
                                if args[1].1 { // second arg is string (text)
                                    text = args[1].0.clone();
                                }
                                if args[3].1 { // fourth arg is string (unique)
                                    unique_id = args[3].0.clone();
                                }
                                let lang_expr = args[0].0.trim();
                                if lang_expr.contains("Language::Ru") || lang_expr.contains("Ru") {
                                    text_language = String::from("Ru");
                                } else {
                                    text_language = String::from("En");
                                }
                            },
                            3 => {
                                // or ($text_language:expr, $text:literal, $language:expr)
                                if args[0].1 && args[2].1 {
                                    // ($text:literal, $language:expr, $uniq:literal)
                                    text = args[0].0.clone();
                                    unique_id = args[2].0.clone();
                                    text_language = String::from("En");
                                } else if args[1].1 {
                                    // ($text_language:expr, $text:literal, $language:expr)
                                    text = args[1].0.clone();
                                    let lang_expr = args[0].0.trim();
                                    if lang_expr.contains("Language::Ru") || lang_expr.contains("Ru") {
                                        text_language = String::from("Ru");
                                    } else {
                                        text_language = String::from("En");
                                    }
                                }
                            },
                            2 => {
                                // ($text:literal, $language:expr)
                                if args[0].1 { // first arg is string (text)
                                    text = args[0].0.clone();
                                    text_language = String::from("En");
                                }
                            },
                            _ => {
                                continue;
                            }
                        }
                    } else if macro_type == 'r' || macro_type == 's' {
                        // 3 args: ($text_language:expr, $text:literal, $uniq:literal)
                        // 2 args: ($text:literal, $uniq:literal)
                        // 2 args: ($text_language:expr, $text:literal)  
                        // 1 arg:  ($text:literal)
                        
                        match args.len() {
                            3 => {
                                // ($text_language:expr, $text:literal, $uniq:literal)
                                if args[1].1 { // second arg is string (text)
                                    text = args[1].0.clone();
                                }
                                if args[2].1 { // third arg is string (unique)
                                    unique_id = args[2].0.clone();
                                }
                                let lang_expr = args[0].0.trim();
                                if lang_expr.contains("Language::Ru") || lang_expr.contains("Ru") {
                                    text_language = String::from("Ru");
                                } else {
                                    text_language = String::from("En");
                                }
                            },
                            2 => {
                                if args[0].1 && args[1].1 {
                                    // ($text:literal, $uniq:literal)
                                    text = args[0].0.clone();
                                    unique_id = args[1].0.clone();
                                    text_language = String::from("En"); // Default
                                } else if args[1].1 {
                                    // ($text_language:expr, $text:literal)
                                    text = args[1].0.clone();
                                    let lang_expr = args[0].0.trim();
                                    if lang_expr.contains("Language::Ru") || lang_expr.contains("Ru") {
                                        text_language = String::from("Ru");
                                    } else {
                                        text_language = String::from("En");
                                    }
                                }
                            },
                            1 => {
                                // ($text:literal)
                                if args[0].1 { // first arg is string (text)
                                    text = args[0].0.clone();
                                    text_language = String::from("En"); // Default
                                }
                            },
                            _ => {
                                continue;
                            }
                        }
                    }
                    
                    if !text.trim().is_empty() {
                        let (identifier, is_manual) = if !unique_id.trim().is_empty() {
                            (unique_id.trim().to_string(), true)
                        } else {
                            (module.clone(), false)
                        };
                        translations.insert((text.trim().to_string(), (identifier, is_manual, text_language)));
                    }
                }
            } else {
                i += 1;
            }
        }
    }
}