use crate::eval::local::types::EvalReport;

const MAX_GOOD_TITLE_LEN: usize = 120;

impl std::fmt::Display for EvalReport {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        writeln!(
            f,
            "=== remem eval-local ({} memories) ===\n",
            self.total_memories
        )?;
        writeln!(
            f,
            "[dedup] {} duplicates in {} groups ({:.1}%)",
            self.dedup.duplicate_count,
            self.dedup.duplicate_groups,
            self.dedup.duplicate_rate * 100.0
        )?;
        if !self.dedup.worst_groups.is_empty() {
            writeln!(f, "  worst:")?;
            for (preview, count) in &self.dedup.worst_groups {
                writeln!(f, "    {}x  {}", count, preview)?;
            }
        }

        writeln!(
            f,
            "\n[project_filter] tested {} entities, {} true leaks / {} hits ({:.1}%)",
            self.project_leak.total_tested,
            self.project_leak.leaked,
            self.project_leak.total_hits,
            self.project_leak.leak_rate * 100.0
        )?;
        writeln!(
            f,
            "  hits: {} project-local, {} global-overlay",
            self.project_leak.project_hits, self.project_leak.global_overlay_hits
        )?;
        writeln!(
            f,
            "\n[title_quality] {:.1}% start with bullet, {:.1}% too long (>{} chars)",
            self.title_quality.bullet_rate * 100.0,
            title_too_long_rate(self),
            MAX_GOOD_TITLE_LEN
        )?;
        writeln!(
            f,
            "\n[self_retrieval] {}/{} ({:.1}%)",
            self.self_retrieval.found,
            self.self_retrieval.total_tested,
            self.self_retrieval.retrieval_rate * 100.0
        )?;
        writeln!(f, "\n--- overall: {:.1}/5.0 ---", self.overall_score())?;
        Ok(())
    }
}

impl EvalReport {
    pub fn overall_score(&self) -> f64 {
        let dedup_score = (1.0 - self.dedup.duplicate_rate).max(0.0) * 5.0;
        let leak_score = (1.0 - self.project_leak.leak_rate).max(0.0) * 5.0;
        let title_score = (1.0 - self.title_quality.bullet_rate).max(0.0) * 5.0;
        let retrieval_score = self.self_retrieval.retrieval_rate * 5.0;

        dedup_score * 0.30 + leak_score * 0.25 + title_score * 0.15 + retrieval_score * 0.30
    }
}

fn title_too_long_rate(report: &EvalReport) -> f64 {
    if report.title_quality.total > 0 {
        report.title_quality.too_long as f64 / report.title_quality.total as f64 * 100.0
    } else {
        0.0
    }
}
