use std::fs;
use std::path::{Path, PathBuf};
use anyhow::Result;
use chrono::Utc;
use crate::github::PendingReview;
pub fn write_review(
dir: &Path,
review: &PendingReview,
claude_summary: Option<&str>,
) -> Result<PathBuf> {
fs::create_dir_all(dir)?;
let slug = slugify(&review.pr_title);
let filename = format!("{}-{}-{}.md", review.repo, review.pr_number, slug);
let path = dir.join(&filename);
let age_days = (Utc::now() - review.created_at).num_days();
let mut content = format!(
"# {title}\n\n\
| Field | Value |\n\
|-------------|-------|\n\
| **Repo** | `{repo}` |\n\
| **PR** | [#{number}]({url}) |\n\
| **Author** | `{author}` |\n\
| **Size** | +{add} / -{del} lines |\n\
| **Branch** | `{branch}` |\n\
| **Draft** | {draft} |\n\
| **Opened** | {opened} ({age} days ago) |\n\n\
## 🔗 Link\n\n\
{url}\n\n",
title = review.pr_title,
repo = review.repo,
number = review.pr_number,
url = review.pr_url,
author = review.pr_author,
add = review.additions,
del = review.deletions,
branch = review.branch,
draft = if review.draft { "Yes" } else { "No" },
opened = review.created_at.format("%Y-%m-%d"),
age = age_days,
);
if let Some(summary) = claude_summary {
content.push_str("## 🤖 Claude Triage\n\n");
content.push_str(summary);
content.push_str("\n\n---\n\n> Generated by prctrl\n");
} else {
content.push_str("## 📝 Notes\n\n_Add your review notes here._\n");
}
fs::write(&path, content)?;
Ok(path)
}
pub fn write_index(dir: &Path, reviews: &[PendingReview]) -> Result<PathBuf> {
fs::create_dir_all(dir)?;
let path = dir.join("INDEX.md");
let mut content = format!(
"# 📋 Pending Reviews — {}\n\n",
Utc::now().format("%Y-%m-%d %H:%M UTC")
);
if reviews.is_empty() {
content.push_str("✅ Nothing to review!\n");
} else {
content.push_str(&format!("{} PR(s) waiting for you.\n\n", reviews.len()));
content.push_str("| # | PR | Repo | Author | Size | Age |\n");
content.push_str("|---|----|----|--------|------|-----|\n");
for r in reviews {
let age = (Utc::now() - r.created_at).num_days();
let slug = slugify(&r.pr_title);
let file = format!("{}-{}-{}.md", r.repo, r.pr_number, slug);
content.push_str(&format!(
"| [#{}]({url}) | [{title}](./{file}) | `{repo}` | `{author}` | +{add}/-{del} | {age}d |\n",
r.pr_number,
url = r.pr_url,
title = r.pr_title,
repo = r.repo,
author = r.pr_author,
add = r.additions,
del = r.deletions,
age = age,
));
}
}
fs::write(&path, content)?;
Ok(path)
}
fn slugify(s: &str) -> String {
s.to_lowercase()
.chars()
.map(|c| if c.is_alphanumeric() { c } else { '-' })
.collect::<String>()
.split('-')
.filter(|s| !s.is_empty())
.collect::<Vec<_>>()
.join("-")
.chars()
.take(40)
.collect()
}