use super::util::{current_dir, today_iso_date};
use koala_health::{build_pruning, close_pruning, pruning_closed_at, write_pruning, CloseError};
use std::path::PathBuf;
use std::process::ExitCode;

fn validate_sprint(sprint: &str) -> Result<(), ExitCode> {
    if !sprint
        .chars()
        .all(|c| c.is_ascii_alphanumeric() || matches!(c, '-' | '_'))
    {
        eprintln!("error: sprint id must match [A-Za-z0-9_-]+; got `{sprint}`");
        return Err(ExitCode::from(2));
    }
    Ok(())
}

pub fn start(root: Option<PathBuf>, sprint: String) -> ExitCode {
    if let Err(c) = validate_sprint(&sprint) {
        return c;
    }
    let root = root.unwrap_or_else(current_dir);
    if let Some(at) = pruning_closed_at(&root, &sprint) {
        eprintln!(
            "warning: sprint `{sprint}` is already closed (closed_at={at}); refreshing anyway"
        );
    }
    let checklist = build_pruning(&root, &sprint);
    match write_pruning(&root, &checklist) {
        Ok(path) => {
            println!(
                "Pruning sprint `{sprint}`: {redlines} redline(s), {advisories} drift advisory line(s).",
                redlines = checklist.redlines.len(),
                advisories = checklist.drift_advisories.len(),
            );
            println!("wrote {}", path.display());
            ExitCode::SUCCESS
        }
        Err(e) => {
            eprintln!("error: cannot write checklist: {e}");
            ExitCode::from(1)
        }
    }
}

pub fn close(root: Option<PathBuf>, sprint: String, at: Option<String>) -> ExitCode {
    if let Err(c) = validate_sprint(&sprint) {
        return c;
    }
    let root = root.unwrap_or_else(current_dir);
    let timestamp = at.unwrap_or_else(|| {
        today_iso_date()
            .map(|d| format!("{d}T00:00:00Z"))
            .unwrap_or_else(|| "unknown".into())
    });
    match close_pruning(&root, &sprint, &timestamp) {
        Ok(r) => {
            println!(
                "Pruning sprint `{sprint}` closed at {at}.",
                at = r.closed_at
            );
            println!("wrote {}", r.marker_path.display());
            ExitCode::SUCCESS
        }
        Err(CloseError::AlreadyClosed { closed_at, .. }) => {
            eprintln!(
                "error: sprint `{sprint}` already closed (closed_at={closed_at}); \
                 delete .koala/pruning/{sprint}.closed to re-open"
            );
            ExitCode::from(1)
        }
        Err(e) => {
            eprintln!("error: {e}");
            ExitCode::from(1)
        }
    }
}
