use anyhow::Result;
use std::path::Path;

use crate::cli::DepAction;
use crate::db;
use crate::ops;

pub fn run(root: &Path, action: &DepAction, json: bool) -> Result<()> {
    let store = db::open(root)?;

    match action {
        DepAction::Add { child, parent } => {
            let child_id = db::resolve_task_id(&store, child, false)?;
            let parent_id = db::resolve_task_id(&store, parent, false)?;
            ops::add_dep(&store, &child_id, &parent_id)?;
            if json {
                println!(
                    "{}",
                    serde_json::json!({"child": child_id, "blocker": parent_id})
                );
            } else {
                let c = crate::color::stdout_theme();
                println!(
                    "{}{child_id}{} blocked by {}{parent_id}{}",
                    c.green, c.reset, c.yellow, c.reset
                );
            }
        }
        DepAction::Rm { child, parent } => {
            let child_id = db::resolve_task_id(&store, child, false)?;
            let parent_id = db::resolve_task_id(&store, parent, true)?;
            ops::remove_dep(&store, &child_id, &parent_id)?;
            if !json {
                let c = crate::color::stdout_theme();
                println!(
                    "{}{child_id}{} no longer blocked by {}{parent_id}{}",
                    c.green, c.reset, c.yellow, c.reset
                );
            }
        }
        DepAction::Tree { id } => {
            let root_id = db::resolve_task_id(&store, id, true)?;
            println!("{}", root_id);
            let mut children: Vec<_> = store
                .list_tasks_unfiltered()?
                .into_iter()
                .filter(|t| t.parent.as_ref() == Some(&root_id))
                .map(|t| t.id)
                .collect();
            children.sort_by(|a, b| a.as_str().cmp(b.as_str()));
            for child in children {
                println!("  {child}");
            }
        }
    }

    Ok(())
}
