sara-tasks 2.7.5

Sara — folder-aware task manager
use anyhow::Result;
use rusqlite::Connection;
use serde_json::{Value, json};

use crate::infrastructure::db;

pub fn link_value(
    conn: &Connection,
    id_or_uuid: &str,
    url: &str,
    label: Option<&str>,
) -> Result<Value> {
    let task = db::resolve_task(conn, id_or_uuid)?;
    let already_linked = db::get_links(conn, &task.uuid)?
        .iter()
        .any(|l| l.url == url);
    if !already_linked {
        db::add_link(conn, &task.uuid, url, label)?;
    }
    Ok(json!({
        "task": task.id,
        "uuid": task.uuid.to_string(),
        "url": url,
        "label": label,
        "already_linked": already_linked,
    }))
}

pub fn link(conn: &Connection, id_or_uuid: &str, url: &str, label: Option<&str>) -> Result<()> {
    let v = link_value(conn, id_or_uuid, url, label)?;
    let task = v["task"].as_i64().unwrap_or(0);
    if v["already_linked"].as_bool() == Some(true) {
        println!("Task {task} is already linked to {url}");
    } else {
        println!("Linked task {task}: {url}");
    }
    Ok(())
}

pub fn unlink_value(conn: &Connection, link_id: i64) -> Result<Value> {
    if db::delete_link(conn, link_id)? {
        Ok(json!({ "link_id": link_id, "removed": true }))
    } else {
        anyhow::bail!("No link with id {link_id}")
    }
}

pub fn unlink_url_value(conn: &Connection, id_or_uuid: &str, url: &str) -> Result<Value> {
    let task = db::resolve_task(conn, id_or_uuid)?;
    let Some(link) = db::get_links(conn, &task.uuid)?
        .into_iter()
        .find(|l| l.url == url)
    else {
        anyhow::bail!("Task {id_or_uuid} has no link to {url}")
    };
    db::delete_link(conn, link.id)?;
    Ok(json!({
        "task": task.id,
        "uuid": task.uuid.to_string(),
        "url": url,
        "link_id": link.id,
        "removed": true,
    }))
}

pub fn unlink(conn: &Connection, link_id: i64) -> Result<()> {
    unlink_value(conn, link_id)?;
    println!("Removed link {link_id}.");
    Ok(())
}