garbage_code_hunter/
reporter.rs

1#[allow(dead_code)]
2use colored::*;
3use std::collections::hash_map::DefaultHasher;
4use std::collections::{BTreeMap, HashMap};
5use std::hash::{Hash, Hasher};
6use std::time::{SystemTime, UNIX_EPOCH};
7
8use crate::analyzer::{CodeIssue, Severity};
9use crate::educational::EducationalAdvisor;
10use crate::hall_of_shame::HallOfShame;
11use crate::i18n::I18n;
12use crate::scoring::{CodeQualityScore, CodeScorer};
13
14pub struct Reporter {
15    harsh_mode: bool,
16    savage_mode: bool,
17    verbose: bool,
18    top_files: usize,
19    max_issues_per_file: usize,
20    summary_only: bool,
21    markdown: bool,
22    i18n: I18n,
23}
24
25#[allow(dead_code)]
26impl Reporter {
27    #[allow(clippy::too_many_arguments)]
28    pub fn new(
29        harsh_mode: bool,
30        savage_mode: bool,
31        verbose: bool,
32        top_files: usize,
33        max_issues_per_file: usize,
34        summary_only: bool,
35        markdown: bool,
36        lang: &str,
37    ) -> Self {
38        Self {
39            harsh_mode,
40            savage_mode,
41            verbose,
42            top_files,
43            max_issues_per_file,
44            summary_only,
45            markdown,
46            i18n: I18n::new(lang),
47        }
48    }
49
50    /// get random roast message
51    fn get_random_roast(&self, category: &str, score: f64, seed: u64) -> String {
52        let roasts = self.get_category_roasts(category, score);
53        if roasts.is_empty() {
54            return if self.i18n.lang == "zh-CN" {
55                "代码需要改进 🔧".to_string()
56            } else {
57                "Code needs improvement 🔧".to_string()
58            };
59        }
60
61        // seed genearte random index
62        let mut hasher = DefaultHasher::new();
63        seed.hash(&mut hasher);
64        category.hash(&mut hasher);
65        let hash = hasher.finish();
66        let index = (hash as usize) % roasts.len();
67
68        roasts[index].to_string()
69    }
70
71    /// get roast message
72    fn get_category_roasts(&self, category: &str, score: f64) -> Vec<&str> {
73        if self.i18n.lang == "zh-CN" {
74            match category {
75                "命名规范" => {
76                    if score >= 80.0 {
77                        vec![
78                            "恭喜!你成功让变量名比注释还难懂 🏆",
79                            "这些变量名是用随机字符生成器起的吗? 🎲",
80                            "变量命名水平堪比密码设置 🔐",
81                            "看到这些变量名,我想起了古代象形文字 📜",
82                            "变量名比我的人生还迷茫 😵‍💫",
83                            "这命名风格很有'艺术感' 🎨",
84                            "变量名的创意程度超越了我的理解 🚀",
85                        ]
86                    } else if score >= 60.0 {
87                        vec![
88                            "变量命名还有改进空间 📝",
89                            "建议给变量起个有意义的名字 💭",
90                            "变量名可以更清晰一些 ✨",
91                            "命名规范需要加强 📚",
92                        ]
93                    } else {
94                        vec!["变量命名还不错 👍", "命名风格可以接受 ✅"]
95                    }
96                }
97                "复杂度" => {
98                    if score >= 80.0 {
99                        vec![
100                            "复杂度爆表!连AI都看不懂了 🤖",
101                            "这代码比迷宫还复杂 🌀",
102                            "嵌套层数比俄罗斯套娃还多 🪆",
103                            "代码复杂度已经超越了人类理解范围 🧠",
104                            "这函数比我的感情生活还复杂 💔",
105                            "建议拆分成多个小函数,拯救一下可读性 🆘",
106                            "复杂度高到需要GPS导航 🗺️",
107                            "这代码比数学公式还抽象 📐",
108                            "嵌套深度堪比洋葱,剥一层哭一次 🧅",
109                            "代码结构比立体拼图还复杂 🧩",
110                            "这复杂度让我想起了哲学问题 🤔",
111                            "函数长度已经突破天际 🚀",
112                            "这代码需要配个说明书 📖",
113                            "复杂度比我的作息时间还乱 ⏰",
114                            "建议给这个函数买个保险 🛡️",
115                        ]
116                    } else if score >= 60.0 {
117                        vec![
118                            "代码有点复杂,建议简化 🔧",
119                            "函数可以拆分得更小一些 ✂️",
120                            "嵌套层数有点多 📚",
121                            "复杂度需要控制一下 ⚖️",
122                            "代码结构可以更清晰 🏗️",
123                            "建议重构一下逻辑 🔄",
124                            "函数职责可以更单一 🎯",
125                            "代码可读性需要提升 👓",
126                        ]
127                    } else {
128                        vec!["代码结构还算清晰 👌", "复杂度控制得不错 ✅"]
129                    }
130                }
131                "代码重复" => {
132                    if score >= 80.0 {
133                        vec![
134                            "建议改名为copy-paste.rs 📋",
135                            "重复代码比我重复的梦还多 💤",
136                            "Ctrl+C 和 Ctrl+V 是你最好的朋友吗? ⌨️",
137                            "代码重复度堪比复读机 🔄",
138                            "这么多重复,建议学学DRY原则 🏜️",
139                            "重复代码多到可以开复制店了 🏪",
140                            "代码重复率比我的日常还高 📈",
141                            "这重复程度可以申请吉尼斯纪录了 🏆",
142                            "代码复制粘贴技能满级 🎮",
143                            "重复代码比回音还响亮 📢",
144                            "这是代码还是复印机作品? 🖨️",
145                            "DRY原则在你这里变成了WET原则 💧",
146                            "重复代码比我的口头禅还频繁 🗣️",
147                            "建议给复制粘贴键盘买个保险 ⌨️",
148                            "代码重复度比镜子还厉害 🪞",
149                        ]
150                    } else if score >= 60.0 {
151                        vec![
152                            "有一些重复代码需要处理 🔧",
153                            "建议提取公共函数 📦",
154                            "重复代码可以优化 ✨",
155                            "考虑重构重复的部分 🔄",
156                            "代码复用性可以提升 🔗",
157                            "建议抽象出通用逻辑 🎯",
158                            "重复部分可以模块化 📋",
159                            "代码结构需要优化 🏗️",
160                        ]
161                    } else {
162                        vec!["代码重复控制得不错 👍", "重复度在可接受范围 ✅"]
163                    }
164                }
165                "Rust功能" => {
166                    if score >= 80.0 {
167                        vec![
168                            "宏定义比我的借口还多 🎭",
169                            "unwrap() 用得比我说'没问题'还频繁 😅",
170                            "String 分配比我花钱还随意 💸",
171                            "这代码让 Rust 编译器都想罢工 🚫",
172                            "panic! 用得这么随意,用户体验堪忧 😱",
173                            "迭代器哭了:为什么不用我? 😢",
174                            "match 表示:我可以更简洁的 💪",
175                            "Vec::new() 比我换衣服还频繁 👕",
176                            "to_string() 调用比我眨眼还多 👁️",
177                            "这代码让 Rust 的零成本抽象哭了 😭",
178                            "错误处理?什么是错误处理? 🤷‍♂️",
179                            "生命周期标注比我的简历还复杂 📄",
180                            "这代码违反了 Rust 的哲学原则 📚",
181                            "建议重新学习 Rust 最佳实践 🎓",
182                            "Rust 社区看到这代码会流泪 🦀",
183                        ]
184                    } else if score >= 60.0 {
185                        vec![
186                            "Rust 特性使用需要改进 🦀",
187                            "建议更好地利用 Rust 的特性 ⚡",
188                            "代码可以更 Rust 化 🔧",
189                            "某些模式可以优化 ✨",
190                            "错误处理可以更优雅 🎭",
191                            "内存管理还有优化空间 💾",
192                            "迭代器使用可以加强 🔄",
193                            "类型系统利用不够充分 📊",
194                        ]
195                    } else {
196                        vec!["Rust 特性使用得不错 🦀", "代码很 Rust 化 ⚡"]
197                    }
198                }
199                _ => vec!["代码需要改进 🔧"],
200            }
201        } else {
202            // 英文版本的吐槽
203            match category {
204                "Naming" => {
205                    if score >= 80.0 {
206                        vec![
207                            "Congrats! Your variable names are more confusing than comments 🏆",
208                            "Did you use a random character generator for these names? 🎲",
209                            "Variable naming skills rival password creation 🔐",
210                            "These names remind me of ancient hieroglyphs 📜",
211                            "Variable names are more lost than my life purpose 😵‍💫",
212                            "This naming style is very 'artistic' 🎨",
213                            "The creativity of these names exceeds my understanding 🚀",
214                            "Variable names harder to decode than alien language 👽",
215                            "These names are more abstract than modern art 🖼️",
216                            "Did you name these variables with your eyes closed? 👀",
217                            "Variable naming master class: how to confuse everyone 🎓",
218                            "These names could win a cryptography contest 🔍",
219                            "Variable names more mysterious than unsolved puzzles 🧩",
220                            "I've seen more meaningful names in spam emails 📧",
221                            "These names make dictionary words jealous 📚",
222                        ]
223                    } else if score >= 60.0 {
224                        vec![
225                            "Variable naming has room for improvement 📝",
226                            "Consider giving variables meaningful names 💭",
227                            "Variable names could be clearer ✨",
228                            "Naming conventions need strengthening 📚",
229                            "Variable readability could be enhanced 👀",
230                            "Naming is an art - keep practicing! 💪",
231                            "Variables could be more expressive 🗣️",
232                            "Naming style needs consistency 📐",
233                        ]
234                    } else {
235                        vec![
236                            "Variable naming is decent 👍",
237                            "Naming style is acceptable ✅",
238                        ]
239                    }
240                }
241                "Complexity" => {
242                    if score >= 80.0 {
243                        vec![
244                            "Complexity off the charts! Even AI can't understand 🤖",
245                            "This code is more complex than a maze 🌀",
246                            "More nesting levels than Russian dolls 🪆",
247                            "Code complexity has transcended human understanding 🧠",
248                            "This function is more complex than my love life 💔",
249                            "Consider splitting into smaller functions to save readability 🆘",
250                            "Complexity so high it needs GPS navigation 🗺️",
251                            "This code is more abstract than quantum physics 📐",
252                            "Nesting deeper than an onion, each layer brings tears 🧅",
253                            "Code structure more complex than a 3D puzzle 🧩",
254                            "This complexity makes philosophy look simple 🤔",
255                            "Function length has reached astronomical proportions 🚀",
256                            "This code needs a user manual 📖",
257                            "Complexity more chaotic than my sleep schedule ⏰",
258                            "Consider getting insurance for this function 🛡️",
259                        ]
260                    } else if score >= 60.0 {
261                        vec![
262                            "Code is a bit complex, consider simplifying 🔧",
263                            "Functions could be split smaller ✂️",
264                            "A bit too many nesting levels 📚",
265                            "Complexity needs some control ⚖️",
266                            "Code structure could be clearer 🏗️",
267                            "Consider refactoring the logic 🔄",
268                            "Function responsibilities could be more focused 🎯",
269                            "Code readability needs improvement 👓",
270                        ]
271                    } else {
272                        vec![
273                            "Code structure is fairly clear 👌",
274                            "Complexity is well controlled ✅",
275                        ]
276                    }
277                }
278                "Duplication" => {
279                    if score >= 80.0 {
280                        vec![
281                            "Consider renaming to copy-paste.rs 📋",
282                            "More duplicate code than my recurring dreams 💤",
283                            "Are Ctrl+C and Ctrl+V your best friends? ⌨️",
284                            "Code duplication rivals a parrot 🔄",
285                            "So much duplication, time to learn DRY principle 🏜️",
286                            "Enough duplicate code to open a copy shop 🏪",
287                            "Code duplication rate higher than my daily routine 📈",
288                            "This duplication level deserves a Guinness World Record 🏆",
289                            "Copy-paste skills have reached maximum level 🎮",
290                            "Duplicate code echoes louder than a canyon 📢",
291                            "Is this code or a photocopier masterpiece? 🖨️",
292                            "DRY principle became WET principle in your hands 💧",
293                            "Code repetition more frequent than my catchphrases 🗣️",
294                            "Consider buying insurance for your copy-paste keys ⌨️",
295                            "Duplication level surpasses hall of mirrors 🪞",
296                        ]
297                    } else if score >= 60.0 {
298                        vec![
299                            "Some duplicate code needs handling 🔧",
300                            "Consider extracting common functions 📦",
301                            "Duplicate code can be optimized ✨",
302                            "Consider refactoring repeated parts 🔄",
303                            "Code reusability could be improved 🔗",
304                            "Consider abstracting common logic 🎯",
305                            "Repeated sections could be modularized 📋",
306                            "Code structure needs optimization 🏗️",
307                        ]
308                    } else {
309                        vec![
310                            "Code duplication is well controlled 👍",
311                            "Duplication within acceptable range ✅",
312                        ]
313                    }
314                }
315                "Rust Features" => {
316                    if score >= 80.0 {
317                        vec![
318                            "More macro definitions than my excuses 🎭",
319                            "unwrap() used more frequently than I say 'no problem' 😅",
320                            "String allocation more casual than my spending 💸",
321                            "This code makes Rust compiler want to quit 🚫",
322                            "panic! used so casually, user experience is questionable 😱",
323                            "Iterators are crying: why don't you use me? 😢",
324                            "match says: I can be more concise 💪",
325                            "Vec::new() calls more frequent than my outfit changes 👕",
326                            "to_string() calls exceed my blink count 👁️",
327                            "This code made Rust's zero-cost abstractions weep 😭",
328                            "Error handling? What's error handling? 🤷‍♂️",
329                            "Lifetime annotations more complex than my resume 📄",
330                            "This code violates Rust's philosophical principles 📚",
331                            "Consider retaking Rust best practices course 🎓",
332                            "Rust community would shed tears seeing this code 🦀",
333                        ]
334                    } else if score >= 60.0 {
335                        vec![
336                            "Rust feature usage needs improvement 🦀",
337                            "Consider better utilization of Rust features ⚡",
338                            "Code could be more Rust-idiomatic 🔧",
339                            "Some patterns can be optimized ✨",
340                            "Error handling could be more elegant 🎭",
341                            "Memory management has room for optimization 💾",
342                            "Iterator usage could be strengthened 🔄",
343                            "Type system utilization is insufficient 📊",
344                        ]
345                    } else {
346                        vec![
347                            "Rust features used well 🦀",
348                            "Code is very Rust-idiomatic ⚡",
349                        ]
350                    }
351                }
352                _ => vec!["Code needs improvement 🔧"],
353            }
354        }
355    }
356
357    #[allow(dead_code)]
358    pub fn report(&self, issues: Vec<CodeIssue>) {
359        self.report_with_metrics(issues, 1, 100);
360    }
361
362    pub fn report_with_enhanced_features(
363        &self,
364        mut issues: Vec<CodeIssue>,
365        file_count: usize,
366        total_lines: usize,
367        educational_advisor: Option<&EducationalAdvisor>,
368        hall_of_shame: Option<&HallOfShame>,
369        show_suggestions: bool,
370    ) {
371        // calculate quality score
372        let scorer = CodeScorer::new();
373        let quality_score = scorer.calculate_score(&issues, file_count, total_lines);
374
375        if issues.is_empty() {
376            self.print_clean_code_message_with_score(&quality_score);
377            return;
378        }
379
380        //sort by severity
381        issues.sort_by(|a, b| {
382            let severity_order = |s: &Severity| match s {
383                Severity::Nuclear => 3,
384                Severity::Spicy => 2,
385                Severity::Mild => 1,
386            };
387            severity_order(&b.severity).cmp(&severity_order(&a.severity))
388        });
389
390        // if harsh mode  only show the most severe issue
391        if self.harsh_mode {
392            issues.retain(|issue| matches!(issue.severity, Severity::Nuclear | Severity::Spicy));
393        }
394
395        if self.markdown {
396            self.print_markdown_report_enhanced(
397                &issues,
398                &quality_score,
399                educational_advisor,
400                hall_of_shame,
401                show_suggestions,
402            );
403        } else {
404            if !self.summary_only {
405                self.print_header(&issues);
406                self.print_quality_score(&quality_score);
407                if self.verbose {
408                    self.print_detailed_analysis(&issues);
409                }
410                self.print_top_files(&issues);
411                self.print_issues_enhanced(&issues, educational_advisor);
412            }
413            self.print_summary_with_score(&issues, &quality_score);
414            if !self.summary_only {
415                // Print hall of shame if requested
416                if let Some(shame) = hall_of_shame {
417                    self.print_hall_of_shame(shame);
418                }
419
420                // Print improvement suggestions if requested
421                if show_suggestions {
422                    if let Some(shame) = hall_of_shame {
423                        self.print_improvement_suggestions(shame);
424                    }
425                }
426
427                // Always show footer for non-enhanced mode
428                if !show_suggestions {
429                    self.print_footer(&issues);
430                }
431            }
432        }
433    }
434
435    pub fn report_with_metrics(
436        &self,
437        mut issues: Vec<CodeIssue>,
438        file_count: usize,
439        total_lines: usize,
440    ) {
441        // calculate quality score
442        let scorer = CodeScorer::new();
443        let quality_score = scorer.calculate_score(&issues, file_count, total_lines);
444
445        if issues.is_empty() {
446            self.print_clean_code_message_with_score(&quality_score);
447            return;
448        }
449
450        //sort by severity
451        issues.sort_by(|a, b| {
452            let severity_order = |s: &Severity| match s {
453                Severity::Nuclear => 3,
454                Severity::Spicy => 2,
455                Severity::Mild => 1,
456            };
457            severity_order(&b.severity).cmp(&severity_order(&a.severity))
458        });
459
460        // if harsh mode  only show the most severe issue
461        if self.harsh_mode {
462            issues.retain(|issue| matches!(issue.severity, Severity::Nuclear | Severity::Spicy));
463        }
464
465        if self.markdown {
466            self.print_markdown_report(&issues);
467        } else {
468            if !self.summary_only {
469                self.print_header(&issues);
470                self.print_quality_score(&quality_score);
471                if self.verbose {
472                    self.print_detailed_analysis(&issues);
473                }
474                self.print_top_files(&issues);
475                self.print_issues(&issues);
476            }
477            self.print_summary_with_score(&issues, &quality_score);
478            if !self.summary_only {
479                self.print_footer(&issues);
480            }
481        }
482    }
483
484    #[allow(dead_code)]
485    fn print_clean_code_message(&self) {
486        if self.markdown {
487            println!("# {}", self.i18n.get("title"));
488            println!();
489            println!("{}", self.i18n.get("clean_code"));
490            println!();
491            println!("{}", self.i18n.get("clean_code_warning"));
492        } else {
493            println!("{}", self.i18n.get("clean_code").bright_green().bold());
494            println!("{}", self.i18n.get("clean_code_warning").yellow());
495        }
496    }
497
498    fn print_clean_code_message_with_score(&self, quality_score: &CodeQualityScore) {
499        if self.markdown {
500            println!("# {}", self.i18n.get("title"));
501            println!();
502            println!("## 🏆 代码质量评分");
503            println!();
504            println!(
505                "**评分**: {:.1}/100 {}",
506                quality_score.total_score,
507                quality_score.quality_level.emoji()
508            );
509            println!(
510                "**等级**: {}",
511                quality_score.quality_level.description(&self.i18n.lang)
512            );
513            println!();
514            println!("{}", self.i18n.get("clean_code"));
515            println!();
516            println!("{}", self.i18n.get("clean_code_warning"));
517        } else {
518            println!("{}", self.i18n.get("clean_code").bright_green().bold());
519            println!();
520            println!(
521                "{} 代码质量评分: {:.1}/100 {}",
522                "🏆".bright_yellow(),
523                quality_score.total_score.to_string().bright_green().bold(),
524                quality_score.quality_level.emoji()
525            );
526            println!(
527                "{} 质量等级: {}",
528                "📊".bright_blue(),
529                quality_score
530                    .quality_level
531                    .description(&self.i18n.lang)
532                    .bright_green()
533                    .bold()
534            );
535            println!("{}", self.i18n.get("clean_code_warning").yellow());
536        }
537    }
538
539    fn print_quality_score(&self, quality_score: &CodeQualityScore) {
540        let title = match self.i18n.lang.as_str() {
541            "zh-CN" => "🏆 代码质量评分",
542            _ => "🏆 Code Quality Score",
543        };
544        println!("{}", title.bright_yellow().bold());
545        println!("{}", "─".repeat(50).bright_black());
546
547        let _score_color = match quality_score.quality_level {
548            crate::scoring::QualityLevel::Excellent => {
549                quality_score.total_score.to_string().bright_green().bold()
550            }
551            crate::scoring::QualityLevel::Good => quality_score.total_score.to_string().green(),
552            crate::scoring::QualityLevel::Average => quality_score.total_score.to_string().yellow(),
553            crate::scoring::QualityLevel::Poor => quality_score.total_score.to_string().red(),
554            crate::scoring::QualityLevel::Terrible => {
555                quality_score.total_score.to_string().bright_red().bold()
556            }
557        };
558
559        let (score_label, level_label) = match self.i18n.lang.as_str() {
560            "zh-CN" => ("📊 总分", "🎯 等级"),
561            _ => ("📊 Score", "🎯 Level"),
562        };
563
564        println!(
565            "   {}: {:.1}/100 {}",
566            score_label,
567            quality_score.total_score,
568            quality_score.quality_level.emoji()
569        );
570        println!(
571            "   {}: {}",
572            level_label,
573            quality_score
574                .quality_level
575                .description(&self.i18n.lang)
576                .bright_white()
577                .bold()
578        );
579
580        if quality_score.total_lines > 0 {
581            let (lines_label, files_label, density_label) = match self.i18n.lang.as_str() {
582                "zh-CN" => ("📏 代码行数", "📁 文件数量", "🔍 问题密度"),
583                _ => ("📏 Lines of Code", "📁 Files", "🔍 Issue Density"),
584            };
585            let density_unit = match self.i18n.lang.as_str() {
586                "zh-CN" => "问题/千行",
587                _ => "issues/1k lines",
588            };
589
590            println!(
591                "   {}: {}",
592                lines_label,
593                quality_score.total_lines.to_string().cyan()
594            );
595            println!(
596                "   {}: {}",
597                files_label,
598                quality_score.file_count.to_string().cyan()
599            );
600            println!(
601                "   {}: {:.2} {}",
602                density_label,
603                quality_score.issue_density.to_string().cyan(),
604                density_unit
605            );
606        }
607
608        if quality_score.severity_distribution.nuclear > 0
609            || quality_score.severity_distribution.spicy > 0
610            || quality_score.severity_distribution.mild > 0
611        {
612            println!();
613            let distribution_title = match self.i18n.lang.as_str() {
614                "zh-CN" => "🎭 问题分布:",
615                _ => "🎭 Issue Distribution:",
616            };
617            let (nuclear_label, spicy_label, mild_label) = match self.i18n.lang.as_str() {
618                "zh-CN" => ("💥 核弹级", "🌶️  严重", "😐 轻微"),
619                _ => ("💥 Nuclear", "🌶️  Spicy", "😐 Mild"),
620            };
621
622            println!("   {distribution_title}");
623            if quality_score.severity_distribution.nuclear > 0 {
624                println!(
625                    "      {}: {}",
626                    nuclear_label,
627                    quality_score
628                        .severity_distribution
629                        .nuclear
630                        .to_string()
631                        .red()
632                        .bold()
633                );
634            }
635            if quality_score.severity_distribution.spicy > 0 {
636                println!(
637                    "      {}: {}",
638                    spicy_label,
639                    quality_score
640                        .severity_distribution
641                        .spicy
642                        .to_string()
643                        .yellow()
644                );
645            }
646            if quality_score.severity_distribution.mild > 0 {
647                println!(
648                    "      {}: {}",
649                    mild_label,
650                    quality_score.severity_distribution.mild.to_string().blue()
651                );
652            }
653        }
654
655        // 显示分类得分(如果有的话)
656        if !quality_score.category_scores.is_empty() && self.verbose {
657            println!();
658            let category_title = match self.i18n.lang.as_str() {
659                "zh-CN" => "📋 分类得分:",
660                _ => "📋 Category Scores:",
661            };
662            println!("   {category_title}");
663            let mut sorted_categories: Vec<_> = quality_score.category_scores.iter().collect();
664            sorted_categories
665                .sort_by(|a, b| b.1.partial_cmp(a.1).unwrap_or(std::cmp::Ordering::Equal));
666
667            for (category, score) in sorted_categories.iter().take(5) {
668                let category_name = match (self.i18n.lang.as_str(), category.as_str()) {
669                    ("zh-CN", "naming") => "命名规范",
670                    ("zh-CN", "complexity") => "复杂度",
671                    ("zh-CN", "rust-basics") => "Rust基础",
672                    ("zh-CN", "advanced-rust") => "高级特性",
673                    ("zh-CN", "rust-features") => "Rust功能",
674                    ("zh-CN", "structure") => "代码结构",
675                    ("zh-CN", "duplication") => "重复代码",
676                    (_, "naming") => "Naming",
677                    (_, "complexity") => "Complexity",
678                    (_, "rust-basics") => "Rust Basics",
679                    (_, "advanced-rust") => "Advanced Rust",
680                    (_, "rust-features") => "Rust Features",
681                    (_, "structure") => "Code Structure",
682                    (_, "duplication") => "Code Duplication",
683                    _ => category,
684                };
685                println!(
686                    "      {} {:.1}",
687                    category_name.cyan(),
688                    score.to_string().yellow()
689                );
690            }
691        }
692
693        println!();
694    }
695
696    fn print_header(&self, issues: &[CodeIssue]) {
697        let total = issues.len();
698        let nuclear = issues
699            .iter()
700            .filter(|i| matches!(i.severity, Severity::Nuclear))
701            .count();
702        let spicy = issues
703            .iter()
704            .filter(|i| matches!(i.severity, Severity::Spicy))
705            .count();
706        let mild = issues
707            .iter()
708            .filter(|i| matches!(i.severity, Severity::Mild))
709            .count();
710
711        println!("{}", self.i18n.get("title").bright_red().bold());
712        println!("{}", self.i18n.get("preparing").yellow());
713        println!();
714
715        println!("{}", self.i18n.get("report_title").bright_red().bold());
716        println!("{}", "─".repeat(50).bright_black());
717
718        if self.savage_mode {
719            println!("{}", self.i18n.get("found_issues").red().bold());
720        } else {
721            println!("{}", self.i18n.get("found_issues").yellow());
722        }
723
724        println!();
725        println!("{}", self.i18n.get("statistics"));
726        println!(
727            "   {} {}",
728            nuclear.to_string().red().bold(),
729            self.i18n.get("nuclear_issues")
730        );
731        println!(
732            "   {} {}",
733            spicy.to_string().yellow().bold(),
734            self.i18n.get("spicy_issues")
735        );
736        println!(
737            "   {} {}",
738            mild.to_string().blue().bold(),
739            self.i18n.get("mild_issues")
740        );
741        println!(
742            "   {} {}",
743            total.to_string().bright_white().bold(),
744            self.i18n.get("total")
745        );
746        println!();
747    }
748
749    fn print_issues(&self, issues: &[CodeIssue]) {
750        let mut file_groups: HashMap<String, Vec<&CodeIssue>> = HashMap::new();
751
752        for issue in issues {
753            let file_name = issue
754                .file_path
755                .file_name()
756                .unwrap_or_default()
757                .to_string_lossy()
758                .to_string();
759            file_groups.entry(file_name).or_default().push(issue);
760        }
761
762        for (file_name, file_issues) in file_groups {
763            println!("{} {}", "📁".bright_blue(), file_name.bright_blue().bold());
764
765            // Group issues by rule type
766            let mut rule_groups: BTreeMap<String, Vec<&CodeIssue>> = BTreeMap::new();
767            for issue in &file_issues {
768                rule_groups
769                    .entry(issue.rule_name.clone())
770                    .or_default()
771                    .push(issue);
772            }
773
774            // Show limited number of issues per rule type
775            let _max_per_rule = 5;
776            let mut total_shown = 0;
777            let max_total = if self.max_issues_per_file > 0 {
778                self.max_issues_per_file
779            } else {
780                usize::MAX
781            };
782
783            // Sort rule groups by severity (most severe first)
784            let mut sorted_rules: Vec<_> = rule_groups.into_iter().collect();
785            sorted_rules.sort_by(|a, b| {
786                let severity_order = |s: &Severity| match s {
787                    Severity::Nuclear => 3,
788                    Severity::Spicy => 2,
789                    Severity::Mild => 1,
790                };
791                let max_severity_a =
792                    a.1.iter()
793                        .map(|i| severity_order(&i.severity))
794                        .max()
795                        .unwrap_or(1);
796                let max_severity_b =
797                    b.1.iter()
798                        .map(|i| severity_order(&i.severity))
799                        .max()
800                        .unwrap_or(1);
801                max_severity_b.cmp(&max_severity_a)
802            });
803
804            for (rule_name, rule_issues) in sorted_rules {
805                if total_shown >= max_total {
806                    break;
807                }
808
809                let rule_issues_len = rule_issues.len();
810
811                // Create compact summary for each rule type
812                if rule_name.contains("naming") || rule_name.contains("single-letter") {
813                    // Collect variable names for naming issues
814                    let bad_names: Vec<String> = rule_issues
815                        .iter()
816                        .filter_map(|issue| {
817                            if let Some(start) = issue.message.find("'") {
818                                issue.message[start + 1..].find("'").map(|end| {
819                                    issue.message[start + 1..start + 1 + end].to_string()
820                                })
821                            } else {
822                                None
823                            }
824                        })
825                        .take(5)
826                        .collect();
827
828                    let names_display = if bad_names.len() < rule_issues_len {
829                        format!("{}, ...", bad_names.join(", "))
830                    } else {
831                        bad_names.join(", ")
832                    };
833
834                    let label = if self.i18n.lang == "zh-CN" {
835                        "变量命名问题"
836                    } else {
837                        "Variable naming issues"
838                    };
839
840                    println!(
841                        "  🏷️ {}: {} ({})",
842                        label.bright_yellow().bold(),
843                        rule_issues_len.to_string().bright_red().bold(),
844                        names_display.bright_black()
845                    );
846                    total_shown += 1;
847                } else if rule_name.contains("duplication") {
848                    let label = if self.i18n.lang == "zh-CN" {
849                        "代码重复问题"
850                    } else {
851                        "Code duplication issues"
852                    };
853
854                    // Extract instance count from message if available
855                    let instance_info = if let Some(first_issue) = rule_issues.first() {
856                        if first_issue.message.contains("instances") {
857                            let parts: Vec<&str> = first_issue.message.split_whitespace().collect();
858                            if let Some(pos) = parts.iter().position(|&x| x == "instances") {
859                                if pos > 0 {
860                                    format!("{} instances", parts[pos - 1])
861                                } else {
862                                    "multiple instances".to_string()
863                                }
864                            } else if self.i18n.lang == "zh-CN" {
865                                "多个代码块".to_string()
866                            } else {
867                                "multiple blocks".to_string()
868                            }
869                        } else if self.i18n.lang == "zh-CN" {
870                            "多个代码块".to_string()
871                        } else {
872                            "multiple blocks".to_string()
873                        }
874                    } else if self.i18n.lang == "zh-CN" {
875                        "多个代码块".to_string()
876                    } else {
877                        "multiple blocks".to_string()
878                    };
879
880                    println!(
881                        "  🔄 {}: {} ({})",
882                        label.bright_cyan().bold(),
883                        rule_issues_len.to_string().bright_cyan().bold(),
884                        instance_info.bright_black()
885                    );
886                    total_shown += 1;
887                } else if rule_name.contains("nesting") {
888                    let label = if self.i18n.lang == "zh-CN" {
889                        "嵌套深度问题"
890                    } else {
891                        "Nesting depth issues"
892                    };
893
894                    // Extract depth range from messages
895                    let depths: Vec<usize> = rule_issues
896                        .iter()
897                        .filter_map(|issue| {
898                            if let Some(start) = issue.message.find("depth: ") {
899                                let depth_str = &issue.message[start + 7..];
900                                if let Some(end) = depth_str.find(')') {
901                                    depth_str[..end].parse().ok()
902                                } else {
903                                    None
904                                }
905                            } else if let Some(start) = issue.message.find("深度: ") {
906                                let depth_str = &issue.message[start + 6..];
907                                if let Some(end) = depth_str.find(')') {
908                                    depth_str[..end].parse().ok()
909                                } else {
910                                    None
911                                }
912                            } else {
913                                None
914                            }
915                        })
916                        .collect();
917
918                    let depth_info = if !depths.is_empty() {
919                        let min_depth = depths.iter().min().unwrap_or(&4);
920                        let max_depth = depths.iter().max().unwrap_or(&8);
921                        if min_depth == max_depth {
922                            format!("depth {min_depth}")
923                        } else {
924                            format!("depth {min_depth}-{max_depth}")
925                        }
926                    } else if self.i18n.lang == "zh-CN" {
927                        "深度嵌套".to_string()
928                    } else {
929                        "deep nesting".to_string()
930                    };
931
932                    println!(
933                        "  📦 {}: {} ({})",
934                        label.bright_magenta().bold(),
935                        rule_issues_len.to_string().bright_magenta().bold(),
936                        depth_info.bright_black()
937                    );
938                    total_shown += 1;
939                } else {
940                    // For other types, show a generic summary with proper translation
941                    let display_name = match (self.i18n.lang.as_str(), rule_name.as_str()) {
942                        ("zh-CN", "panic-abuse") => "panic 滥用",
943                        ("zh-CN", "god-function") => "上帝函数",
944                        ("zh-CN", "magic-number") => "魔法数字",
945                        ("zh-CN", "todo-comment") => "TODO 注释",
946                        ("zh-CN", "println-debugging") => "println 调试",
947                        ("zh-CN", "string-abuse") => "String 滥用",
948                        ("zh-CN", "vec-abuse") => "Vec 滥用",
949                        ("zh-CN", "iterator-abuse") => "迭代器滥用",
950                        ("zh-CN", "match-abuse") => "Match 滥用",
951                        ("zh-CN", "hungarian-notation") => "匈牙利命名法",
952                        ("zh-CN", "abbreviation-abuse") => "过度缩写",
953                        ("zh-CN", "meaningless-naming") => "无意义命名",
954                        ("zh-CN", "commented-code") => "被注释代码",
955                        ("zh-CN", "dead-code") => "死代码",
956                        _ => &rule_name.replace("-", " "),
957                    };
958                    println!(
959                        "  ⚠️ {}: {}",
960                        display_name.bright_yellow().bold(),
961                        rule_issues_len.to_string().bright_yellow().bold()
962                    );
963                    total_shown += 1;
964                }
965            }
966            println!();
967        }
968    }
969
970    fn print_issue(&self, issue: &CodeIssue) {
971        // Choose icon and color based on rule type
972        if issue.rule_name.contains("duplication") {
973            let message = if self.i18n.lang == "zh-CN" {
974                &issue.message
975            } else {
976                // Translate common duplication messages to English
977                if issue.message.contains("相似代码块") {
978                    "Found similar code blocks, consider refactoring into functions"
979                } else if issue.message.contains("DRY原则哭了") {
980                    "Code duplication detected, DRY principle violated"
981                } else {
982                    &issue.message
983                }
984            };
985            println!(
986                "  {} {} {}",
987                "🔄".bright_cyan(),
988                "duplicate".bright_black(),
989                message.bright_cyan().bold()
990            );
991        } else if issue.rule_name.contains("nesting") {
992            let message = if self.i18n.lang == "zh-CN" {
993                &issue.message
994            } else {
995                // Translate common nesting messages to English
996                if issue.message.contains("俄罗斯套娃") {
997                    "Nesting deeper than Russian dolls, are you writing a maze?"
998                } else if issue.message.contains("挖到地心") {
999                    "Nesting so deep, trying to dig to the Earth's core?"
1000                } else if issue.message.contains("像洋葱一样") {
1001                    "Code nested like an onion, makes me want to cry"
1002                } else {
1003                    &issue.message
1004                }
1005            };
1006            println!(
1007                "  {} {} {}",
1008                "📦".bright_magenta(),
1009                "nesting".bright_black(),
1010                message.bright_magenta()
1011            );
1012        } else {
1013            // Default based on severity
1014            let severity_icon = match issue.severity {
1015                Severity::Nuclear => "💥",
1016                Severity::Spicy => "🌶️",
1017                Severity::Mild => "😐",
1018            };
1019
1020            let line_info = format!("{}:{}", issue.line, issue.column);
1021            let colored_message = match issue.severity {
1022                Severity::Nuclear => issue.message.red().bold(),
1023                Severity::Spicy => issue.message.yellow(),
1024                Severity::Mild => issue.message.blue(),
1025            };
1026
1027            let _final_message = if self.savage_mode {
1028                self.make_message_savage(&issue.message)
1029            } else {
1030                issue.message.clone()
1031            };
1032
1033            println!(
1034                "  {} {} {}",
1035                severity_icon.bright_yellow(),
1036                line_info.bright_black(),
1037                colored_message
1038            );
1039        }
1040    }
1041
1042    fn make_message_savage(&self, message: &str) -> String {
1043        let savage_prefixes = [
1044            "🔥 严重警告:",
1045            "💀 代码死刑:",
1046            "🗑️ 垃圾警报:",
1047            "😱 恐怖发现:",
1048            "🤮 令人作呕:",
1049        ];
1050
1051        let prefix = savage_prefixes[message.len() % savage_prefixes.len()];
1052        format!("{prefix} {message}")
1053    }
1054
1055    fn print_summary_with_score(&self, issues: &[CodeIssue], quality_score: &CodeQualityScore) {
1056        // Print enhanced summary with better layout
1057        self.print_enhanced_summary(issues, quality_score);
1058    }
1059
1060    fn print_enhanced_summary(&self, issues: &[CodeIssue], quality_score: &CodeQualityScore) {
1061        println!();
1062
1063        // Header with decorative border
1064        if self.i18n.lang == "zh-CN" {
1065            println!("{}", "🏆 代码质量报告".bright_cyan().bold());
1066            println!("{}", "═".repeat(60).bright_black());
1067        } else {
1068            println!("{}", "🏆 Code Quality Report".bright_cyan().bold());
1069            println!("{}", "═".repeat(60).bright_black());
1070        }
1071
1072        // Overall score section with card-like layout
1073        let score_bar = self.create_enhanced_score_bar(quality_score.total_score);
1074        let score_emoji = quality_score.quality_level.emoji();
1075        let score_desc = quality_score.quality_level.description(&self.i18n.lang);
1076
1077        if self.i18n.lang == "zh-CN" {
1078            println!("╭─ 📊 总体评分 ─────────────────────────────────────────╮");
1079            println!("│                                                      │");
1080
1081            // Format score line with proper alignment
1082            let score_text = format!("总分: {:.1}/100", quality_score.total_score);
1083            let status_text = format!("({score_emoji} {score_desc})");
1084            println!(
1085                "│  {}  {}  {}│",
1086                score_text.bright_red().bold(),
1087                score_bar,
1088                status_text.bright_black()
1089            );
1090
1091            // Add file statistics
1092            let file_count = issues
1093                .iter()
1094                .map(|i| &i.file_path)
1095                .collect::<std::collections::HashSet<_>>()
1096                .len();
1097            let total_issues = issues.len();
1098            println!("│                                                      │");
1099            let stats_text = format!("分析文件: {file_count} 个    问题总数: {total_issues} 个");
1100            println!("│  {stats_text}                              │");
1101            println!("│                                                      │");
1102            println!("╰──────────────────────────────────────────────────────╯");
1103        } else {
1104            println!("╭─ 📊 Overall Score ───────────────────────────────────╮");
1105            println!("│                                                      │");
1106
1107            // Format score line with proper alignment
1108            let score_text = format!("Score: {:.1}/100", quality_score.total_score);
1109            let status_text = format!("({score_emoji} {score_desc})");
1110            println!(
1111                "│  {}  {}  {}│",
1112                score_text.bright_red().bold(),
1113                score_bar,
1114                status_text.bright_black()
1115            );
1116
1117            // Add file statistics
1118            let file_count = issues
1119                .iter()
1120                .map(|i| &i.file_path)
1121                .collect::<std::collections::HashSet<_>>()
1122                .len();
1123            let total_issues = issues.len();
1124            println!("│                                                      │");
1125            let stats_text =
1126                format!("Files analyzed: {file_count}    Total issues: {total_issues}");
1127            println!("│  {stats_text}                           │");
1128            println!("│                                                      │");
1129            println!("╰──────────────────────────────────────────────────────╯");
1130        }
1131
1132        println!();
1133        self.print_category_scores_enhanced(&quality_score.category_scores);
1134
1135        println!();
1136        self.print_quality_legend();
1137
1138        // Only show improvement suggestions if explicitly requested via --suggestions flag
1139        // This makes the --suggestions parameter more meaningful
1140    }
1141
1142    fn create_enhanced_score_bar(&self, score: f64) -> String {
1143        let bar_length = 20;
1144        // 注意:分数越高代码越烂,所以用红色表示高分
1145        let filled_length = ((score / 100.0) * bar_length as f64) as usize;
1146        let empty_length = bar_length - filled_length;
1147
1148        let filled_char = if score >= 80.0 {
1149            "█".red()
1150        } else if score >= 60.0 {
1151            "█".yellow()
1152        } else if score >= 40.0 {
1153            "█".blue()
1154        } else {
1155            "█".green()
1156        };
1157
1158        let empty_char = "▒".bright_black();
1159
1160        format!(
1161            "{}{}",
1162            filled_char.to_string().repeat(filled_length),
1163            empty_char.to_string().repeat(empty_length)
1164        )
1165    }
1166
1167    fn print_category_scores_enhanced(
1168        &self,
1169        category_scores: &std::collections::HashMap<String, f64>,
1170    ) {
1171        if self.i18n.lang == "zh-CN" {
1172            println!("{}", "📋 分类评分详情".bright_yellow().bold());
1173        } else {
1174            println!("{}", "📋 Category Scores".bright_yellow().bold());
1175        }
1176        println!("{}", "─".repeat(60).bright_black());
1177
1178        // Define category display order and info
1179        let categories = [
1180            ("naming", "命名规范", "Naming", "🏷️"),
1181            ("complexity", "复杂度", "Complexity", "🧩"),
1182            ("duplication", "代码重复", "Duplication", "🔄"),
1183            ("rust-basics", "Rust基础", "Rust Basics", "🦀"),
1184            ("advanced-rust", "高级特性", "Advanced Rust", "⚡"),
1185            ("rust-features", "Rust功能", "Rust Features", "🚀"),
1186            ("structure", "代码结构", "Code Structure", "🏗️"),
1187        ];
1188
1189        for (category_key, zh_name, en_name, icon) in &categories {
1190            if let Some(score) = category_scores.get(*category_key) {
1191                let display_name = if self.i18n.lang == "zh-CN" {
1192                    zh_name
1193                } else {
1194                    en_name
1195                };
1196                let (status_icon, status_text) = self.get_score_status(*score);
1197                let score_bar = self.create_enhanced_score_bar(*score);
1198
1199                // Enhanced display with progress bar
1200                let score_unit = if self.i18n.lang == "zh-CN" { "分" } else { "" };
1201                println!(
1202                    "   {} {} [{:>3}{}] {} {}",
1203                    status_icon,
1204                    format!("{icon} {display_name}").bright_white().bold(),
1205                    format!("{score:.0}").bright_cyan(),
1206                    score_unit,
1207                    score_bar,
1208                    status_text.bright_black()
1209                );
1210
1211                // if score is high (code is bad), add a roast
1212                if let Some(roast) = self.get_category_roast(category_key, *score) {
1213                    println!("       💬 {}", roast.bright_yellow().italic());
1214                }
1215            }
1216        }
1217        println!();
1218    }
1219
1220    fn print_quality_legend(&self) {
1221        if self.i18n.lang == "zh-CN" {
1222            println!(
1223                "{}",
1224                "📏 评分标准 (分数越高代码越烂)".bright_yellow().bold()
1225            );
1226            println!("{}", "─".repeat(40).bright_black());
1227            println!("   💀 81-100分: 糟糕,急需重写    🔥 61-80分: 较差,建议重构");
1228            println!("   ⚠️  41-60分: 一般,需要改进    ✅ 21-40分: 良好,还有提升空间");
1229            println!("   🌟 0-20分: 优秀,继续保持");
1230        } else {
1231            println!(
1232                "{}",
1233                "📏 Scoring Scale (higher score = worse code)"
1234                    .bright_yellow()
1235                    .bold()
1236            );
1237            println!("{}", "─".repeat(50).bright_black());
1238            println!(
1239                "   💀 81-100: Terrible, rewrite needed    🔥 61-80: Poor, refactoring recommended"
1240            );
1241            println!(
1242                "   ⚠️  41-60: Average, needs improvement   ✅ 21-40: Good, room for improvement"
1243            );
1244            println!("   🌟 0-20: Excellent, keep it up");
1245        }
1246    }
1247
1248    fn print_improvement_suggestions_enhanced(&self, quality_score: &CodeQualityScore) {
1249        if self.i18n.lang == "zh-CN" {
1250            println!("{}", "💡 改进建议".bright_green().bold());
1251        } else {
1252            println!("{}", "💡 Improvement Suggestions".bright_green().bold());
1253        }
1254        println!("{}", "─".repeat(50).bright_black());
1255
1256        let suggestions = self.generate_improvement_suggestions_from_score(quality_score);
1257        for suggestion in suggestions {
1258            println!("   • {}", suggestion.green());
1259        }
1260    }
1261
1262    fn generate_improvement_suggestions_from_score(
1263        &self,
1264        quality_score: &CodeQualityScore,
1265    ) -> Vec<String> {
1266        let mut suggestions = Vec::new();
1267
1268        // Sort categories by score (worst first)
1269        let mut sorted_categories: Vec<_> = quality_score.category_scores.iter().collect();
1270        sorted_categories.sort_by(|a, b| b.1.partial_cmp(a.1).unwrap_or(std::cmp::Ordering::Equal));
1271
1272        for (category, score) in sorted_categories.iter().take(3) {
1273            if **score > 60.0 {
1274                let suggestion = match (self.i18n.lang.as_str(), category.as_str()) {
1275                    ("zh-CN", "naming") => "🏷️ 重点改进变量和函数命名 - 清晰的名称让代码自文档化",
1276                    ("zh-CN", "complexity") => "🧩 将复杂函数分解为更小、更专注的函数",
1277                    ("zh-CN", "duplication") => "🔄 消除重复代码,提取公共函数和模块",
1278                    ("zh-CN", "rust-features") => "🦀 学习和应用 Rust 最佳实践,减少不必要的分配",
1279                    (_, "naming") => "🏷️ Focus on improving variable and function naming - clear names make code self-documenting",
1280                    (_, "complexity") => "🧩 Break down complex functions into smaller, focused functions",
1281                    (_, "duplication") => "🔄 Eliminate code duplication, extract common functions and modules",
1282                    (_, "rust-features") => "🦀 Learn and apply Rust best practices, reduce unnecessary allocations",
1283                    _ => continue,
1284                };
1285                suggestions.push(suggestion.to_string());
1286            }
1287        }
1288
1289        if suggestions.is_empty() {
1290            if self.i18n.lang == "zh-CN" {
1291                suggestions.push("🎉 代码质量不错!继续保持良好的编程习惯".to_string());
1292            } else {
1293                suggestions.push(
1294                    "🎉 Code quality looks good! Keep up the good programming habits".to_string(),
1295                );
1296            }
1297        }
1298
1299        suggestions
1300    }
1301
1302    fn print_old_summary_with_score(&self, issues: &[CodeIssue], quality_score: &CodeQualityScore) {
1303        // Print detailed scoring breakdown
1304        self.print_scoring_breakdown(issues, quality_score);
1305        let _nuclear_count = issues
1306            .iter()
1307            .filter(|i| matches!(i.severity, Severity::Nuclear))
1308            .count();
1309        let _total_count = issues.len();
1310
1311        println!("{}", self.i18n.get("summary").bright_white().bold());
1312        println!("{}", "─".repeat(50).bright_black());
1313
1314        // 显示评分总结
1315        let score_summary = match quality_score.quality_level {
1316            crate::scoring::QualityLevel::Excellent => match self.i18n.lang.as_str() {
1317                "zh-CN" => format!(
1318                    "🏆 代码质量优秀!评分: {:.1}/100",
1319                    quality_score.total_score
1320                ),
1321                _ => format!(
1322                    "🏆 Excellent code quality! Score: {:.1}/100",
1323                    quality_score.total_score
1324                ),
1325            },
1326            crate::scoring::QualityLevel::Good => match self.i18n.lang.as_str() {
1327                "zh-CN" => format!(
1328                    "👍 代码质量良好,评分: {:.1}/100",
1329                    quality_score.total_score
1330                ),
1331                _ => format!(
1332                    "👍 Good code quality, Score: {:.1}/100",
1333                    quality_score.total_score
1334                ),
1335            },
1336            crate::scoring::QualityLevel::Average => match self.i18n.lang.as_str() {
1337                "zh-CN" => format!(
1338                    "😐 代码质量一般,评分: {:.1}/100,还有改进空间",
1339                    quality_score.total_score
1340                ),
1341                _ => format!(
1342                    "😐 Average code quality, Score: {:.1}/100, room for improvement",
1343                    quality_score.total_score
1344                ),
1345            },
1346            crate::scoring::QualityLevel::Poor => match self.i18n.lang.as_str() {
1347                "zh-CN" => format!(
1348                    "😟 代码质量较差,评分: {:.1}/100,建议重构",
1349                    quality_score.total_score
1350                ),
1351                _ => format!(
1352                    "😟 Poor code quality, Score: {:.1}/100, refactoring recommended",
1353                    quality_score.total_score
1354                ),
1355            },
1356            crate::scoring::QualityLevel::Terrible => match self.i18n.lang.as_str() {
1357                "zh-CN" => format!(
1358                    "💀 代码质量糟糕,评分: {:.1}/100,急需重写",
1359                    quality_score.total_score
1360                ),
1361                _ => format!(
1362                    "💀 Terrible code quality, Score: {:.1}/100, rewrite urgently needed",
1363                    quality_score.total_score
1364                ),
1365            },
1366        };
1367
1368        let score_color = match quality_score.quality_level {
1369            crate::scoring::QualityLevel::Excellent => score_summary.bright_green().bold(),
1370            crate::scoring::QualityLevel::Good => score_summary.green(),
1371            crate::scoring::QualityLevel::Average => score_summary.yellow(),
1372            crate::scoring::QualityLevel::Poor => score_summary.red(),
1373            crate::scoring::QualityLevel::Terrible => score_summary.bright_red().bold(),
1374        };
1375
1376        println!("{score_color}");
1377        println!();
1378
1379        let nuclear_count = issues
1380            .iter()
1381            .filter(|i| matches!(i.severity, Severity::Nuclear))
1382            .count();
1383        let total_count = issues.len();
1384
1385        let summary_message = if nuclear_count > 0 {
1386            if self.savage_mode {
1387                match self.i18n.lang.as_str() {
1388                    "zh-CN" => "你的代码质量堪忧,建议重新学习编程基础 💀".to_string(),
1389                    _ => "Your code quality is concerning, suggest learning programming basics again 💀".to_string(),
1390                }
1391            } else {
1392                match self.i18n.lang.as_str() {
1393                    "zh-CN" => "发现了一些严重问题,建议优先修复核弹级问题 🔥".to_string(),
1394                    _ => "Found some serious issues, suggest fixing nuclear problems first 🔥"
1395                        .to_string(),
1396                }
1397            }
1398        } else if total_count > 10 {
1399            match self.i18n.lang.as_str() {
1400                "zh-CN" => "问题有点多,建议分批修复 📝".to_string(),
1401                _ => "Quite a few issues, suggest fixing them in batches 📝".to_string(),
1402            }
1403        } else {
1404            match self.i18n.lang.as_str() {
1405                "zh-CN" => "问题不多,稍微改进一下就好了 👍".to_string(),
1406                _ => "Not many issues, just need some minor improvements 👍".to_string(),
1407            }
1408        };
1409
1410        let color = if nuclear_count > 0 {
1411            summary_message.red().bold()
1412        } else if total_count > 10 {
1413            summary_message.yellow()
1414        } else {
1415            summary_message.green()
1416        };
1417
1418        println!("{color}");
1419    }
1420
1421    fn print_scoring_breakdown(&self, _issues: &[CodeIssue], quality_score: &CodeQualityScore) {
1422        let title = if self.i18n.lang == "zh-CN" {
1423            "📊 评分详情"
1424        } else {
1425            "📊 Scoring Details"
1426        };
1427
1428        println!("\n{}", title.bright_cyan().bold());
1429        println!("{}", "─".repeat(50).bright_black());
1430
1431        // Show category scores
1432        self.print_category_scores(&quality_score.category_scores);
1433
1434        // Show weighted calculation
1435        self.print_weighted_calculation(&quality_score.category_scores, quality_score.total_score);
1436
1437        // Show scoring scale
1438        let scale_title = if self.i18n.lang == "zh-CN" {
1439            "\n📏 评分标准 (分数越高代码越烂):"
1440        } else {
1441            "\n📏 Scoring Scale (higher score = worse code):"
1442        };
1443
1444        println!("{}", scale_title.bright_yellow());
1445        if self.i18n.lang == "zh-CN" {
1446            println!("  💀 81-100: 糟糕    🔥 61-80: 较差    ⚠️ 41-60: 一般");
1447            println!("  ✅ 21-40: 良好     🌟 0-20: 优秀");
1448        } else {
1449            println!("  💀 81-100: Terrible    🔥 61-80: Poor    ⚠️ 41-60: Average");
1450            println!("  ✅ 21-40: Good         🌟 0-20: Excellent");
1451        }
1452    }
1453
1454    fn calculate_base_score_for_display(
1455        &self,
1456        issues: &[CodeIssue],
1457        scorer: &crate::scoring::CodeScorer,
1458    ) -> f64 {
1459        let mut score = 0.0;
1460        for issue in issues {
1461            let rule_weight = scorer.rule_weights.get(&issue.rule_name).unwrap_or(&1.0);
1462            let severity_weight = match issue.severity {
1463                crate::analyzer::Severity::Nuclear => 10.0,
1464                crate::analyzer::Severity::Spicy => 5.0,
1465                crate::analyzer::Severity::Mild => 2.0,
1466            };
1467            score += rule_weight * severity_weight;
1468        }
1469        score
1470    }
1471
1472    fn calculate_density_penalty_for_display(
1473        &self,
1474        issue_count: usize,
1475        file_count: usize,
1476        total_lines: usize,
1477    ) -> f64 {
1478        if total_lines == 0 || file_count == 0 {
1479            return 0.0;
1480        }
1481
1482        let issues_per_1000_lines = (issue_count as f64 / total_lines as f64) * 1000.0;
1483        let issues_per_file = issue_count as f64 / file_count as f64;
1484
1485        let density_penalty = match issues_per_1000_lines {
1486            x if x > 50.0 => 25.0,
1487            x if x > 30.0 => 15.0,
1488            x if x > 20.0 => 10.0,
1489            x if x > 10.0 => 5.0,
1490            _ => 0.0,
1491        };
1492
1493        let file_penalty = match issues_per_file {
1494            x if x > 20.0 => 15.0,
1495            x if x > 10.0 => 10.0,
1496            x if x > 5.0 => 5.0,
1497            _ => 0.0,
1498        };
1499
1500        density_penalty + file_penalty
1501    }
1502
1503    fn calculate_severity_penalty_for_display(
1504        &self,
1505        distribution: &crate::scoring::SeverityDistribution,
1506    ) -> f64 {
1507        let mut penalty = 0.0;
1508
1509        if distribution.nuclear > 0 {
1510            penalty += 20.0 + (distribution.nuclear as f64 - 1.0) * 5.0;
1511        }
1512
1513        if distribution.spicy > 5 {
1514            penalty += (distribution.spicy as f64 - 5.0) * 2.0;
1515        }
1516
1517        if distribution.mild > 20 {
1518            penalty += (distribution.mild as f64 - 20.0) * 0.5;
1519        }
1520
1521        penalty
1522    }
1523
1524    fn print_category_scores(&self, category_scores: &std::collections::HashMap<String, f64>) {
1525        let title = if self.i18n.lang == "zh-CN" {
1526            "📋 分类评分详情:"
1527        } else {
1528            "📋 Category Scores:"
1529        };
1530
1531        println!("{}", title.bright_yellow());
1532
1533        // Define category display order and info
1534        let categories = [
1535            ("naming", "命名规范", "Naming", "🏷️"),
1536            ("complexity", "复杂度", "Complexity", "🧩"),
1537            ("duplication", "代码重复", "Duplication", "🔄"),
1538            ("rust-basics", "Rust基础", "Rust Basics", "🦀"),
1539            ("advanced-rust", "高级特性", "Advanced Rust", "⚡"),
1540            ("rust-features", "Rust功能", "Rust Features", "🚀"),
1541            ("structure", "代码结构", "Code Structure", "🏗️"),
1542        ];
1543
1544        for (category_key, zh_name, en_name, icon) in &categories {
1545            if let Some(score) = category_scores.get(*category_key) {
1546                let display_name = if self.i18n.lang == "zh-CN" {
1547                    zh_name
1548                } else {
1549                    en_name
1550                };
1551                let (status_icon, status_text) = self.get_score_status(*score);
1552
1553                // basic display
1554                let score_unit = if self.i18n.lang == "zh-CN" { "分" } else { "" };
1555                println!(
1556                    "  {} {} {}{}     {}",
1557                    status_icon,
1558                    format!("{icon} {display_name}").bright_white(),
1559                    format!("{score:.0}").bright_cyan(),
1560                    score_unit,
1561                    status_text.bright_black()
1562                );
1563
1564                // if score is high (code is bad), add a roast
1565                if let Some(roast) = self.get_category_roast(category_key, *score) {
1566                    println!("    💬 {}", roast.bright_yellow().italic());
1567                }
1568            }
1569        }
1570        println!();
1571    }
1572
1573    fn get_score_status(&self, score: f64) -> (&str, &str) {
1574        // 注意:分数越高代码越烂
1575        match score as u32 {
1576            81..=100 => (
1577                "⚠",
1578                if self.i18n.lang == "zh-CN" {
1579                    "糟糕,急需修复"
1580                } else {
1581                    "Terrible, urgent fixes needed"
1582                },
1583            ),
1584            61..=80 => (
1585                "•",
1586                if self.i18n.lang == "zh-CN" {
1587                    "较差,建议重构"
1588                } else {
1589                    "Poor, refactoring recommended"
1590                },
1591            ),
1592            41..=60 => (
1593                "○",
1594                if self.i18n.lang == "zh-CN" {
1595                    "一般,需要改进"
1596                } else {
1597                    "Average, needs improvement"
1598                },
1599            ),
1600            21..=40 => (
1601                "✓",
1602                if self.i18n.lang == "zh-CN" {
1603                    "良好,还有提升空间"
1604                } else {
1605                    "Good, room for improvement"
1606                },
1607            ),
1608            _ => (
1609                "✓✓",
1610                if self.i18n.lang == "zh-CN" {
1611                    "优秀,继续保持"
1612                } else {
1613                    "Excellent, keep it up"
1614                },
1615            ),
1616        }
1617    }
1618
1619    fn get_category_roast(&self, category: &str, score: f64) -> Option<String> {
1620        // only roast if score is high (code is bad)
1621        if score < 60.0 {
1622            return None;
1623        }
1624
1625        // 使用新的随机吐槽系统,支持中英文
1626        let category_name = if self.i18n.lang == "zh-CN" {
1627            match category {
1628                "naming" => "命名规范",
1629                "complexity" => "复杂度",
1630                "duplication" => "代码重复",
1631                "rust-features" => "Rust功能",
1632                _ => category,
1633            }
1634        } else {
1635            match category {
1636                "naming" => "Naming",
1637                "complexity" => "Complexity",
1638                "duplication" => "Duplication",
1639                "rust-features" => "Rust Features",
1640                _ => category,
1641            }
1642        };
1643
1644        // 使用时间戳作为种子,确保每次运行都有不同的吐槽
1645        let timestamp = SystemTime::now()
1646            .duration_since(UNIX_EPOCH)
1647            .unwrap_or_default()
1648            .as_millis() as u64;
1649        let seed = timestamp + (score * 1000.0) as u64;
1650        let roast_message = self.get_random_roast(category_name, score, seed);
1651
1652        if roast_message.is_empty() {
1653            None
1654        } else {
1655            Some(roast_message)
1656        }
1657    }
1658
1659    fn print_weighted_calculation(
1660        &self,
1661        category_scores: &std::collections::HashMap<String, f64>,
1662        _total_score: f64,
1663    ) {
1664        let calc_title = if self.i18n.lang == "zh-CN" {
1665            "🧮 加权计算:"
1666        } else {
1667            "🧮 Weighted Calculation:"
1668        };
1669
1670        println!("{}", calc_title.bright_yellow());
1671
1672        // Show the calculation formula
1673        let weights = [
1674            ("naming", 0.25, "命名规范", "Naming"),
1675            ("complexity", 0.20, "复杂度", "Complexity"),
1676            ("duplication", 0.15, "代码重复", "Duplication"),
1677            ("rust-basics", 0.15, "Rust基础", "Rust Basics"),
1678            ("advanced-rust", 0.10, "高级特性", "Advanced Rust"),
1679            ("rust-features", 0.10, "Rust功能", "Rust Features"),
1680            ("structure", 0.05, "代码结构", "Code Structure"),
1681        ];
1682
1683        let mut calculation_parts = Vec::new();
1684        let mut weighted_sum = 0.0;
1685
1686        for (category_key, weight, _zh_name, _en_name) in &weights {
1687            if let Some(score) = category_scores.get(*category_key) {
1688                let weighted_value = score * weight;
1689                weighted_sum += weighted_value;
1690                calculation_parts.push(format!("{score:.1}×{weight:.2}"));
1691            }
1692        }
1693
1694        if self.i18n.lang == "zh-CN" {
1695            println!(
1696                "  评分计算: ({}) ÷ 1.00 = {}",
1697                calculation_parts.join(" + ").bright_white(),
1698                format!("{weighted_sum:.1}").bright_green().bold()
1699            );
1700        } else {
1701            println!(
1702                "  Score calculation: ({}) ÷ 1.00 = {}",
1703                calculation_parts.join(" + ").bright_white(),
1704                format!("{weighted_sum:.1}").bright_green().bold()
1705            );
1706        }
1707    }
1708
1709    fn print_detailed_base_score_breakdown(
1710        &self,
1711        issues: &[CodeIssue],
1712        scorer: &crate::scoring::CodeScorer,
1713    ) {
1714        // Group issues by rule type and calculate scores
1715        let mut rule_scores: std::collections::HashMap<String, (usize, f64)> =
1716            std::collections::HashMap::new();
1717
1718        for issue in issues {
1719            let rule_weight = scorer.rule_weights.get(&issue.rule_name).unwrap_or(&1.0);
1720            let severity_weight = match issue.severity {
1721                crate::analyzer::Severity::Nuclear => 10.0,
1722                crate::analyzer::Severity::Spicy => 5.0,
1723                crate::analyzer::Severity::Mild => 2.0,
1724            };
1725            let issue_score = rule_weight * severity_weight;
1726
1727            let entry = rule_scores
1728                .entry(issue.rule_name.clone())
1729                .or_insert((0, 0.0));
1730            entry.0 += 1; // count
1731            entry.1 += issue_score; // total score
1732        }
1733
1734        // Sort by score (highest first)
1735        let mut sorted_rules: Vec<_> = rule_scores.into_iter().collect();
1736        sorted_rules.sort_by(|a, b| {
1737            b.1 .1
1738                .partial_cmp(&a.1 .1)
1739                .unwrap_or(std::cmp::Ordering::Equal)
1740        });
1741
1742        let breakdown_title = if self.i18n.lang == "zh-CN" {
1743            "🔍 基础分数详细计算:"
1744        } else {
1745            "🔍 Base score detailed calculation:"
1746        };
1747
1748        println!("{}", breakdown_title.bright_yellow());
1749
1750        for (rule_name, (count, total_score)) in sorted_rules.iter().take(10) {
1751            let rule_weight = scorer.rule_weights.get(rule_name).unwrap_or(&1.0);
1752
1753            let rule_display = match (self.i18n.lang.as_str(), rule_name.as_str()) {
1754                ("zh-CN", "terrible-naming") => "糟糕命名",
1755                ("zh-CN", "single-letter-variable") => "单字母变量",
1756                ("zh-CN", "deep-nesting") => "深度嵌套",
1757                ("zh-CN", "code-duplication") => "代码重复",
1758                ("zh-CN", "long-function") => "超长函数",
1759                ("zh-CN", "macro-abuse") => "宏滥用",
1760                (_, "terrible-naming") => "Terrible naming",
1761                (_, "single-letter-variable") => "Single letter vars",
1762                (_, "deep-nesting") => "Deep nesting",
1763                (_, "code-duplication") => "Code duplication",
1764                (_, "long-function") => "Long function",
1765                (_, "macro-abuse") => "Macro abuse",
1766                _ => rule_name,
1767            };
1768
1769            if self.i18n.lang == "zh-CN" {
1770                println!(
1771                    "  • {} × {} (权重{:.1}) = {}",
1772                    format!("{count}").cyan(),
1773                    rule_display.bright_white(),
1774                    format!("{rule_weight:.1}").yellow(),
1775                    format!("{total_score:.1}").bright_red()
1776                );
1777            } else {
1778                println!(
1779                    "  • {} × {} (weight {:.1}) = {}",
1780                    format!("{count}").cyan(),
1781                    rule_display.bright_white(),
1782                    format!("{rule_weight:.1}").yellow(),
1783                    format!("{total_score:.1}").bright_red()
1784                );
1785            }
1786        }
1787        println!();
1788    }
1789
1790    fn print_footer(&self, _issues: &[CodeIssue]) {
1791        // Footer without improvement suggestions - suggestions are now only shown with --suggestions flag
1792        println!();
1793        if self.i18n.lang == "zh-CN" {
1794            println!("{}", "继续努力,让代码变得更好!🚀".bright_cyan());
1795        } else {
1796            println!(
1797                "{}",
1798                "Keep working to make your code better! 🚀".bright_cyan()
1799            );
1800        }
1801    }
1802
1803    fn print_top_files(&self, issues: &[CodeIssue]) {
1804        if self.top_files == 0 {
1805            return;
1806        }
1807
1808        let mut file_issue_counts: HashMap<String, usize> = HashMap::new();
1809        for issue in issues {
1810            let file_name = issue
1811                .file_path
1812                .file_name()
1813                .unwrap_or_default()
1814                .to_string_lossy()
1815                .to_string();
1816            *file_issue_counts.entry(file_name).or_insert(0) += 1;
1817        }
1818
1819        let mut sorted_files: Vec<_> = file_issue_counts.into_iter().collect();
1820        sorted_files.sort_by(|a, b| b.1.cmp(&a.1));
1821
1822        if !sorted_files.is_empty() {
1823            println!("{}", self.i18n.get("top_files").bright_yellow().bold());
1824            println!("{}", "─".repeat(50).bright_black());
1825
1826            for (i, (file_name, count)) in sorted_files.iter().take(self.top_files).enumerate() {
1827                let rank = format!("{}.", i + 1);
1828                println!(
1829                    "   {} {} ({} issues)",
1830                    rank.bright_white(),
1831                    file_name.bright_blue(),
1832                    count.to_string().red()
1833                );
1834            }
1835            println!();
1836        }
1837    }
1838
1839    fn print_detailed_analysis(&self, issues: &[CodeIssue]) {
1840        println!(
1841            "{}",
1842            self.i18n.get("detailed_analysis").bright_magenta().bold()
1843        );
1844        println!("{}", "─".repeat(50).bright_black());
1845
1846        let mut rule_stats: HashMap<String, usize> = HashMap::new();
1847        for issue in issues {
1848            *rule_stats.entry(issue.rule_name.clone()).or_insert(0) += 1;
1849        }
1850
1851        let rule_descriptions = match self.i18n.lang.as_str() {
1852            "zh-CN" => [
1853                ("terrible-naming", "糟糕的变量命名"),
1854                ("single-letter-variable", "单字母变量"),
1855                ("deep-nesting", "过度嵌套"),
1856                ("long-function", "超长函数"),
1857                ("unwrap-abuse", "unwrap() 滥用"),
1858                ("unnecessary-clone", "不必要的 clone()"),
1859            ]
1860            .iter()
1861            .cloned()
1862            .collect::<HashMap<_, _>>(),
1863            _ => [
1864                ("terrible-naming", "Terrible variable naming"),
1865                ("single-letter-variable", "Single letter variables"),
1866                ("deep-nesting", "Deep nesting"),
1867                ("long-function", "Long functions"),
1868                ("unwrap-abuse", "unwrap() abuse"),
1869                ("unnecessary-clone", "Unnecessary clone()"),
1870            ]
1871            .iter()
1872            .cloned()
1873            .collect::<HashMap<_, _>>(),
1874        };
1875
1876        for (rule_name, count) in rule_stats {
1877            let rule_name_str = rule_name.as_str();
1878
1879            // 获取规则的中文显示名称
1880            let display_name = if self.i18n.lang == "zh-CN" {
1881                match rule_name_str {
1882                    "terrible-naming" => "糟糕的变量命名",
1883                    "single-letter-variable" => "单字母变量",
1884                    "deep-nesting" => "过度嵌套",
1885                    "long-function" => "超长函数",
1886                    "unwrap-abuse" => "unwrap() 滥用",
1887                    "unnecessary-clone" => "不必要的 clone()",
1888                    "panic-abuse" => "panic 滥用",
1889                    "god-function" => "上帝函数",
1890                    "magic-number" => "魔法数字",
1891                    "todo-comment" => "TODO 注释",
1892                    "println-debugging" => "println 调试",
1893                    "string-abuse" => "String 滥用",
1894                    "vec-abuse" => "Vec 滥用",
1895                    "iterator-abuse" => "迭代器滥用",
1896                    "match-abuse" => "Match 滥用",
1897                    "hungarian-notation" => "匈牙利命名法",
1898                    "abbreviation-abuse" => "过度缩写",
1899                    "meaningless-naming" => "无意义命名",
1900                    "commented-code" => "被注释代码",
1901                    "dead-code" => "死代码",
1902                    "code-duplication" => "代码重复",
1903                    "macro-abuse" => "宏滥用",
1904                    _ => rule_name_str,
1905                }
1906            } else {
1907                rule_descriptions
1908                    .get(rule_name_str)
1909                    .unwrap_or(&rule_name_str)
1910            };
1911
1912            let issues_text = if self.i18n.lang == "zh-CN" {
1913                "个问题"
1914            } else {
1915                "issues"
1916            };
1917
1918            println!(
1919                "   📌 {}: {} {}",
1920                display_name.cyan(),
1921                count.to_string().yellow(),
1922                issues_text
1923            );
1924        }
1925        println!();
1926    }
1927
1928    fn print_markdown_report(&self, issues: &[CodeIssue]) {
1929        let total = issues.len();
1930        let nuclear = issues
1931            .iter()
1932            .filter(|i| matches!(i.severity, Severity::Nuclear))
1933            .count();
1934        let spicy = issues
1935            .iter()
1936            .filter(|i| matches!(i.severity, Severity::Spicy))
1937            .count();
1938        let mild = issues
1939            .iter()
1940            .filter(|i| matches!(i.severity, Severity::Mild))
1941            .count();
1942
1943        println!("# {}", self.i18n.get("title"));
1944        println!();
1945        println!("## {}", self.i18n.get("statistics"));
1946        println!();
1947        println!("| Severity | Count | Description |");
1948        println!("| --- | --- | --- |");
1949        println!(
1950            "| 🔥 Nuclear | {} | {} |",
1951            nuclear,
1952            self.i18n.get("nuclear_issues")
1953        );
1954        println!(
1955            "| 🌶️ Spicy | {} | {} |",
1956            spicy,
1957            self.i18n.get("spicy_issues")
1958        );
1959        println!("| 😐 Mild | {} | {} |", mild, self.i18n.get("mild_issues"));
1960        println!(
1961            "| **Total** | **{}** | **{}** |",
1962            total,
1963            self.i18n.get("total")
1964        );
1965        println!();
1966
1967        if self.verbose {
1968            println!("## {}", self.i18n.get("detailed_analysis"));
1969            println!();
1970
1971            let mut rule_stats: HashMap<String, usize> = HashMap::new();
1972            for issue in issues {
1973                *rule_stats.entry(issue.rule_name.clone()).or_insert(0) += 1;
1974            }
1975
1976            for (rule_name, count) in rule_stats {
1977                println!("- **{rule_name}**: {count} issues");
1978            }
1979            println!();
1980        }
1981
1982        println!("## Issues by File");
1983        println!();
1984
1985        let mut file_groups: BTreeMap<String, Vec<&CodeIssue>> = BTreeMap::new();
1986        for issue in issues {
1987            let file_name = issue
1988                .file_path
1989                .file_name()
1990                .unwrap_or_default()
1991                .to_string_lossy()
1992                .to_string();
1993            file_groups.entry(file_name).or_default().push(issue);
1994        }
1995
1996        for (file_name, file_issues) in file_groups {
1997            println!("### 📁 {file_name}");
1998            println!();
1999
2000            let issues_to_show = if self.max_issues_per_file > 0 {
2001                file_issues
2002                    .into_iter()
2003                    .take(self.max_issues_per_file)
2004                    .collect::<Vec<_>>()
2005            } else {
2006                file_issues
2007            };
2008
2009            for issue in issues_to_show {
2010                let severity_icon = match issue.severity {
2011                    Severity::Nuclear => "💥",
2012                    Severity::Spicy => "🌶️",
2013                    Severity::Mild => "😐",
2014                };
2015
2016                let messages = self.i18n.get_roast_messages(&issue.rule_name);
2017                let message = if !messages.is_empty() {
2018                    messages[issue.line % messages.len()].clone()
2019                } else {
2020                    issue.message.clone()
2021                };
2022
2023                println!(
2024                    "- {} **Line {}:{}** - {}",
2025                    severity_icon, issue.line, issue.column, message
2026                );
2027            }
2028            println!();
2029        }
2030
2031        println!("## {}", self.i18n.get("suggestions"));
2032        println!();
2033
2034        let rule_names: Vec<String> = issues
2035            .iter()
2036            .map(|issue| issue.rule_name.clone())
2037            .collect::<std::collections::HashSet<_>>()
2038            .into_iter()
2039            .collect();
2040
2041        let suggestions = self.i18n.get_suggestions(&rule_names);
2042        for suggestion in suggestions {
2043            println!("- {suggestion}");
2044        }
2045    }
2046
2047    fn print_issues_enhanced(
2048        &self,
2049        issues: &[CodeIssue],
2050        educational_advisor: Option<&EducationalAdvisor>,
2051    ) {
2052        let mut file_groups: HashMap<String, Vec<&CodeIssue>> = HashMap::new();
2053
2054        for issue in issues {
2055            let file_name = issue
2056                .file_path
2057                .file_name()
2058                .unwrap_or_default()
2059                .to_string_lossy()
2060                .to_string();
2061            file_groups.entry(file_name).or_default().push(issue);
2062        }
2063
2064        for (file_name, file_issues) in file_groups {
2065            println!("{} {}", "📁".bright_blue(), file_name.bright_blue().bold());
2066
2067            // Group issues by rule type and count them
2068            let mut rule_groups: BTreeMap<String, Vec<&CodeIssue>> = BTreeMap::new();
2069            for issue in &file_issues {
2070                rule_groups
2071                    .entry(issue.rule_name.clone())
2072                    .or_default()
2073                    .push(issue);
2074            }
2075
2076            // Sort rule groups by count (most frequent first)
2077            let mut sorted_rules: Vec<_> = rule_groups.into_iter().collect();
2078            sorted_rules.sort_by(|a, b| b.1.len().cmp(&a.1.len()));
2079
2080            // Display grouped issues with counts and examples
2081            for (rule_name, rule_issues) in sorted_rules {
2082                let count = rule_issues.len();
2083                let icon = self.get_rule_icon(&rule_name);
2084                let translated_name = if self.i18n.lang == "zh-CN" {
2085                    self.translate_rule_display_name(&rule_name)
2086                } else {
2087                    rule_name.replace("-", " ")
2088                };
2089
2090                // Show count and some example variable names for naming issues
2091                if rule_name.contains("naming") {
2092                    let examples: Vec<String> = rule_issues
2093                        .iter()
2094                        .take(5)
2095                        .filter_map(|issue| {
2096                            // Extract variable name from message
2097                            if let Some(start) = issue.message.find("'") {
2098                                issue.message[start + 1..].find("'").map(|end| {
2099                                    issue.message[start + 1..start + 1 + end].to_string()
2100                                })
2101                            } else {
2102                                None
2103                            }
2104                        })
2105                        .collect();
2106
2107                    if !examples.is_empty() {
2108                        println!(
2109                            "  {} {}: {} ({})",
2110                            icon,
2111                            translated_name,
2112                            count,
2113                            examples.join(", ")
2114                        );
2115                    } else {
2116                        println!("  {icon} {translated_name}: {count}");
2117                    }
2118                } else if rule_name.contains("duplication") {
2119                    // Show instance count for duplication
2120                    if let Some(first_issue) = rule_issues.first() {
2121                        if let Some(instances_start) = first_issue.message.find("发现 ") {
2122                            if let Some(instances_end) =
2123                                first_issue.message[instances_start..].find(" 个")
2124                            {
2125                                let instances_str = &first_issue.message
2126                                    [instances_start + 3..instances_start + instances_end];
2127                                println!("  {icon} {translated_name}: {count} ({instances_str} instances)");
2128                            } else {
2129                                println!("  {icon} {translated_name}: {count}");
2130                            }
2131                        } else if let Some(instances_start) =
2132                            first_issue.message.find("Similar code blocks detected: ")
2133                        {
2134                            if let Some(instances_end) =
2135                                first_issue.message[instances_start..].find(" instances")
2136                            {
2137                                let instances_str = &first_issue.message
2138                                    [instances_start + 30..instances_start + instances_end];
2139                                println!("  {icon} {translated_name}: {count} ({instances_str} instances)");
2140                            } else {
2141                                println!("  {icon} {translated_name}: {count}");
2142                            }
2143                        } else {
2144                            println!("  {icon} {translated_name}: {count}");
2145                        }
2146                    } else {
2147                        println!("  {icon} {translated_name}: {count}");
2148                    }
2149                } else {
2150                    println!("  {icon} {translated_name}: {count}");
2151                }
2152
2153                // Show educational advice if requested (only for the first occurrence of each rule)
2154                if let Some(advisor) = educational_advisor {
2155                    if let Some(advice) = advisor.get_advice(&rule_name) {
2156                        self.print_educational_advice(advice);
2157                    }
2158                }
2159            }
2160            println!();
2161        }
2162    }
2163
2164    fn get_rule_icon(&self, rule_name: &str) -> &'static str {
2165        match rule_name {
2166            name if name.contains("naming") => "🏷️",
2167            name if name.contains("nesting") => "📦",
2168            name if name.contains("duplication") => "🔄",
2169            name if name.contains("function") => "⚠️",
2170            name if name.contains("unwrap") => "🛡️",
2171            name if name.contains("string") => "📝",
2172            name if name.contains("println") => "🔍",
2173            name if name.contains("magic") => "🔢",
2174            name if name.contains("panic") => "💥",
2175            name if name.contains("todo") => "📋",
2176            name if name.contains("import") => "📦",
2177            name if name.contains("file") => "📄",
2178            name if name.contains("module") => "🏗️",
2179            _ => "⚠️",
2180        }
2181    }
2182
2183    fn translate_rule_display_name(&self, rule_name: &str) -> String {
2184        match rule_name {
2185            "terrible-naming" => "变量命名问题".to_string(),
2186            "meaningless-naming" => "无意义命名问题".to_string(),
2187            "deep-nesting" => "嵌套深度问题".to_string(),
2188            "duplication" => "代码重复问题".to_string(),
2189            "code-duplication" => "代码重复问题".to_string(),
2190            "long-function" => "过长函数".to_string(),
2191            "god-function" => "上帝函数".to_string(),
2192            "unwrap-abuse" => "unwrap滥用".to_string(),
2193            "string-abuse" => "字符串滥用".to_string(),
2194            "println-debugging" => "println调试".to_string(),
2195            "magic-number" => "魔法数字".to_string(),
2196            "panic-abuse" => "panic滥用".to_string(),
2197            "todo-comment" => "TODO注释".to_string(),
2198            "file-too-long" => "文件过长".to_string(),
2199            "unordered-imports" => "导入混乱".to_string(),
2200            "deep-module-nesting" => "模块嵌套过深".to_string(),
2201            "macro-abuse" => "宏滥用".to_string(),
2202            "abbreviation-abuse" => "缩写滥用".to_string(),
2203            "hungarian-notation" => "匈牙利命名法".to_string(),
2204            "single-letter-variable" => "单字母变量".to_string(),
2205            "iterator-abuse" => "迭代器滥用".to_string(),
2206            "match-abuse" => "match滥用".to_string(),
2207            "vec-abuse" => "Vec滥用".to_string(),
2208            "dead-code" => "死代码".to_string(),
2209            "commented-code" => "注释代码".to_string(),
2210            "unnecessary-clone" => "不必要克隆".to_string(),
2211            "channel-abuse" => "通道滥用".to_string(),
2212            "async-abuse" => "异步滥用".to_string(),
2213            "dyn-trait-abuse" => "动态trait滥用".to_string(),
2214            "unsafe-abuse" => "unsafe滥用".to_string(),
2215            "ffi-abuse" => "FFI滥用".to_string(),
2216            "pattern-matching-abuse" => "模式匹配滥用".to_string(),
2217            "reference-abuse" => "引用滥用".to_string(),
2218            "box-abuse" => "Box滥用".to_string(),
2219            "slice-abuse" => "切片滥用".to_string(),
2220            "module-complexity" => "模块复杂度".to_string(),
2221            _ => rule_name.replace("-", " "),
2222        }
2223    }
2224
2225    fn print_educational_advice(&self, advice: &crate::educational::EducationalAdvice) {
2226        println!("    {}", "💡 Educational Advice:".bright_yellow().bold());
2227        println!(
2228            "    {}",
2229            format!("Why it's bad: {}", advice.why_bad).yellow()
2230        );
2231        println!(
2232            "    {}",
2233            format!("How to fix: {}", advice.how_to_fix).green()
2234        );
2235
2236        if let Some(ref bad_example) = advice.example_bad {
2237            println!("    {}", "❌ Bad example:".red());
2238            println!("    {}", format!("    {bad_example}").bright_black());
2239        }
2240
2241        if let Some(ref good_example) = advice.example_good {
2242            println!("    {}", "✅ Good example:".green());
2243            println!("    {}", format!("    {good_example}").bright_black());
2244        }
2245
2246        if let Some(ref tip) = advice.best_practice_tip {
2247            println!("    {}", format!("💡 Tip: {tip}").cyan());
2248        }
2249
2250        if let Some(ref link) = advice.rust_docs_link {
2251            println!("    {}", format!("📚 Learn more: {link}").blue());
2252        }
2253        println!();
2254    }
2255
2256    fn print_hall_of_shame(&self, hall_of_shame: &HallOfShame) {
2257        let stats = hall_of_shame.generate_shame_report();
2258
2259        println!();
2260        if self.i18n.lang == "zh-CN" {
2261            println!("{}", "🏆 问题最多的文件".bright_red().bold());
2262        } else {
2263            println!(
2264                "{}",
2265                "🏆 Hall of Shame - Worst Offenders".bright_red().bold()
2266            );
2267        }
2268        println!("{}", "─".repeat(60).bright_black());
2269
2270        if stats.hall_of_shame.is_empty() {
2271            if self.i18n.lang == "zh-CN" {
2272                println!("🎉 没有文件进入耻辱榜!干得好!");
2273            } else {
2274                println!("🎉 No files in the hall of shame! Great job!");
2275            }
2276            return;
2277        }
2278
2279        if self.i18n.lang == "zh-CN" {
2280            println!("📊 项目统计:");
2281            println!(
2282                "   分析文件数: {}",
2283                stats.total_files_analyzed.to_string().cyan()
2284            );
2285            println!("   总问题数: {}", stats.total_issues.to_string().red());
2286            println!(
2287                "   垃圾密度: {:.2} 问题/1000行",
2288                stats.garbage_density.to_string().yellow()
2289            );
2290        } else {
2291            println!("📊 Project Statistics:");
2292            println!(
2293                "   Files analyzed: {}",
2294                stats.total_files_analyzed.to_string().cyan()
2295            );
2296            println!("   Total issues: {}", stats.total_issues.to_string().red());
2297            println!(
2298                "   Garbage density: {:.2} issues/1000 lines",
2299                stats.garbage_density.to_string().yellow()
2300            );
2301        }
2302        println!();
2303
2304        if self.i18n.lang == "zh-CN" {
2305            println!("🗑️ 问题最多的 {} 个文件:", stats.hall_of_shame.len().min(5));
2306        } else {
2307            println!("🗑️ Top {} Worst Files:", stats.hall_of_shame.len().min(5));
2308        }
2309
2310        for (i, entry) in stats.hall_of_shame.iter().take(5).enumerate() {
2311            let file_name = entry
2312                .file_path
2313                .file_name()
2314                .unwrap_or_default()
2315                .to_string_lossy();
2316
2317            if self.i18n.lang == "zh-CN" {
2318                println!(
2319                    "   {}. {} ({} 个问题)",
2320                    (i + 1).to_string().bright_white(),
2321                    file_name.bright_red().bold(),
2322                    entry.total_issues.to_string().red()
2323                );
2324
2325                println!(
2326                    "      💥 严重: {}, 🌶️ 中等: {}, 😐 轻微: {}",
2327                    entry.nuclear_issues.to_string().red(),
2328                    entry.spicy_issues.to_string().yellow(),
2329                    entry.mild_issues.to_string().blue()
2330                );
2331            } else {
2332                println!(
2333                    "   {}. {} ({} issues)",
2334                    (i + 1).to_string().bright_white(),
2335                    file_name.bright_red().bold(),
2336                    entry.total_issues.to_string().red()
2337                );
2338
2339                println!(
2340                    "      💥 Nuclear: {}, 🌶️ Spicy: {}, 😐 Mild: {}",
2341                    entry.nuclear_issues.to_string().red(),
2342                    entry.spicy_issues.to_string().yellow(),
2343                    entry.mild_issues.to_string().blue()
2344                );
2345            }
2346        }
2347        println!();
2348
2349        if self.i18n.lang == "zh-CN" {
2350            println!("🔥 最常见问题:");
2351        } else {
2352            println!("🔥 Most Common Issues:");
2353        }
2354
2355        for (i, pattern) in stats.most_common_patterns.iter().take(5).enumerate() {
2356            if self.i18n.lang == "zh-CN" {
2357                println!(
2358                    "   {}. {} ({} 次出现)",
2359                    (i + 1).to_string().bright_white(),
2360                    self.translate_rule_name(&pattern.rule_name).bright_yellow(),
2361                    pattern.count.to_string().red()
2362                );
2363            } else {
2364                println!(
2365                    "   {}. {} ({} occurrences)",
2366                    (i + 1).to_string().bright_white(),
2367                    pattern.rule_name.bright_yellow(),
2368                    pattern.count.to_string().red()
2369                );
2370            }
2371        }
2372        println!();
2373    }
2374
2375    fn translate_rule_name(&self, rule_name: &str) -> String {
2376        if self.i18n.lang != "zh-CN" {
2377            return rule_name.to_string();
2378        }
2379
2380        match rule_name {
2381            "terrible-naming" => "糟糕命名".to_string(),
2382            "meaningless-naming" => "无意义命名".to_string(),
2383            "magic-number" => "魔法数字".to_string(),
2384            "macro-abuse" => "宏滥用".to_string(),
2385            "deep-nesting" => "深层嵌套".to_string(),
2386            "unwrap-abuse" => "unwrap滥用".to_string(),
2387            "string-abuse" => "字符串滥用".to_string(),
2388            "println-debugging" => "println调试".to_string(),
2389            "long-function" => "过长函数".to_string(),
2390            "god-function" => "上帝函数".to_string(),
2391            "file-too-long" => "文件过长".to_string(),
2392            "unordered-imports" => "导入混乱".to_string(),
2393            "deep-module-nesting" => "模块嵌套过深".to_string(),
2394            _ => rule_name.to_string(),
2395        }
2396    }
2397
2398    fn print_improvement_suggestions(&self, hall_of_shame: &HallOfShame) {
2399        let suggestions = hall_of_shame.get_improvement_suggestions(&self.i18n.lang);
2400
2401        println!();
2402        if self.i18n.lang == "zh-CN" {
2403            println!("{}", "💡 改进建议".bright_green().bold());
2404        } else {
2405            println!("{}", "💡 Improvement Suggestions".bright_green().bold());
2406        }
2407        println!("{}", "─".repeat(50).bright_black());
2408
2409        for suggestion in suggestions {
2410            println!("   {}", suggestion.green());
2411        }
2412        println!();
2413    }
2414
2415    fn print_markdown_report_enhanced(
2416        &self,
2417        issues: &[CodeIssue],
2418        quality_score: &CodeQualityScore,
2419        educational_advisor: Option<&EducationalAdvisor>,
2420        hall_of_shame: Option<&HallOfShame>,
2421        show_suggestions: bool,
2422    ) {
2423        // First print the regular markdown report
2424        self.print_markdown_report(issues);
2425
2426        // Add quality score section
2427        println!("## 🏆 Code Quality Score");
2428        println!();
2429        println!(
2430            "**Score**: {:.1}/100 {}",
2431            quality_score.total_score,
2432            quality_score.quality_level.emoji()
2433        );
2434        println!(
2435            "**Level**: {}",
2436            quality_score.quality_level.description(&self.i18n.lang)
2437        );
2438        println!();
2439
2440        // Print hall of shame in markdown if requested
2441        if let Some(shame) = hall_of_shame {
2442            self.print_markdown_hall_of_shame(shame);
2443        }
2444
2445        // Print improvement suggestions in markdown if requested
2446        if show_suggestions {
2447            if let Some(shame) = hall_of_shame {
2448                self.print_markdown_improvement_suggestions(shame);
2449            }
2450        }
2451
2452        // Print educational content in markdown if requested
2453        if educational_advisor.is_some() {
2454            self.print_markdown_educational_section(issues, educational_advisor);
2455        }
2456    }
2457
2458    fn print_markdown_hall_of_shame(&self, hall_of_shame: &HallOfShame) {
2459        let stats = hall_of_shame.generate_shame_report();
2460
2461        println!("## 🏆 Hall of Shame");
2462        println!();
2463
2464        if stats.hall_of_shame.is_empty() {
2465            println!("🎉 No files in the hall of shame! Great job!");
2466            return;
2467        }
2468
2469        println!("### 📊 Project Statistics");
2470        println!();
2471        println!("| Metric | Value |");
2472        println!("| --- | --- |");
2473        println!("| Files analyzed | {} |", stats.total_files_analyzed);
2474        println!("| Total issues | {} |", stats.total_issues);
2475        println!(
2476            "| Garbage density | {:.2} issues/1000 lines |",
2477            stats.garbage_density
2478        );
2479        println!();
2480
2481        println!("### 🗑️ Worst Files");
2482        println!();
2483        println!("| Rank | File | Shame Score | Nuclear | Spicy | Mild |");
2484        println!("| --- | --- | --- | --- | --- | --- |");
2485
2486        for (i, entry) in stats.hall_of_shame.iter().take(5).enumerate() {
2487            let file_name = entry
2488                .file_path
2489                .file_name()
2490                .unwrap_or_default()
2491                .to_string_lossy();
2492
2493            println!(
2494                "| {} | {} | {:.1} | {} | {} | {} |",
2495                i + 1,
2496                file_name,
2497                entry.shame_score,
2498                entry.nuclear_issues,
2499                entry.spicy_issues,
2500                entry.mild_issues
2501            );
2502        }
2503        println!();
2504
2505        println!("### 🔥 Most Common Issues");
2506        println!();
2507        println!("| Rank | Issue Type | Count |");
2508        println!("| --- | --- | --- |");
2509
2510        for (i, pattern) in stats.most_common_patterns.iter().take(5).enumerate() {
2511            println!("| {} | {} | {} |", i + 1, pattern.rule_name, pattern.count);
2512        }
2513        println!();
2514    }
2515
2516    fn print_markdown_improvement_suggestions(&self, hall_of_shame: &HallOfShame) {
2517        let suggestions = hall_of_shame.get_improvement_suggestions(&self.i18n.lang);
2518
2519        if self.i18n.lang == "zh-CN" {
2520            println!("## 💡 改进建议");
2521        } else {
2522            println!("## 💡 Improvement Suggestions");
2523        }
2524        println!();
2525
2526        for suggestion in suggestions {
2527            println!("- {suggestion}");
2528        }
2529        println!();
2530    }
2531
2532    fn print_markdown_educational_section(
2533        &self,
2534        issues: &[CodeIssue],
2535        educational_advisor: Option<&EducationalAdvisor>,
2536    ) {
2537        if let Some(advisor) = educational_advisor {
2538            println!("## 📚 Educational Content");
2539            println!();
2540
2541            // Get unique rule names
2542            let mut rule_names: std::collections::HashSet<String> =
2543                std::collections::HashSet::new();
2544            for issue in issues {
2545                rule_names.insert(issue.rule_name.clone());
2546            }
2547
2548            for rule_name in rule_names {
2549                if let Some(advice) = advisor.get_advice(&rule_name) {
2550                    println!("### 📖 {}", rule_name.replace("-", " "));
2551                    println!();
2552                    println!("**Why it's problematic:**");
2553                    println!("{}", advice.why_bad);
2554                    println!();
2555                    println!("**How to fix:**");
2556                    println!("{}", advice.how_to_fix);
2557                    println!();
2558
2559                    if let Some(ref bad_example) = advice.example_bad {
2560                        println!("**❌ Bad example:**");
2561                        println!("```rust");
2562                        println!("{bad_example}");
2563                        println!("```");
2564                        println!();
2565                    }
2566
2567                    if let Some(ref good_example) = advice.example_good {
2568                        println!("**✅ Good example:**");
2569                        println!("```rust");
2570                        println!("{good_example}");
2571                        println!("```");
2572                        println!();
2573                    }
2574
2575                    if let Some(ref tip) = advice.best_practice_tip {
2576                        println!("**💡 Best Practice Tip:**");
2577                        println!("{tip}");
2578                        println!();
2579                    }
2580
2581                    if let Some(ref link) = advice.rust_docs_link {
2582                        println!("**📚 Learn More:**");
2583                        println!("[Rust Documentation]({link})");
2584                        println!();
2585                    }
2586                }
2587            }
2588        }
2589    }
2590}