//! `delete` verb — hard DELETE by id, OR soft (if schema has an
//! `archived` integer field, flips it to 1).

use crate::error::VerbError;
use crate::schema::EntitySchema;
use crate::verbs::pk;
use rusqlite::Connection;
use serde_json::{json, Value};

pub fn run(
    conn: &Connection,
    schema: &EntitySchema,
    input: Value,
) -> Result<Value, VerbError> {
    if !schema.verb_enabled("delete") {
        return Err(VerbError::VerbDisabled {
            verb: "delete".into(),
            schema: schema.name.into(),
        });
    }
    let id = pk::extract(schema, &input, "delete")?;
    let soft = input.get("soft").and_then(|v| v.as_bool()).unwrap_or(false);

    let rows = if soft && has_archived_field(schema) {
        conn.execute(
            &format!(
                "UPDATE {} SET archived = 1 WHERE {}=?1",
                schema.table,
                schema.pk().name
            ),
            rusqlite::params![id.as_sql()],
        )?
    } else {
        if schema.fts_columns.is_some() {
            conn.execute(
                &format!("DELETE FROM fts_{} WHERE {}_id=?1", schema.table, schema.table),
                rusqlite::params![id.as_sql()],
            )?;
        }
        conn.execute(
            &format!(
                "DELETE FROM {} WHERE {}=?1",
                schema.table,
                schema.pk().name
            ),
            rusqlite::params![id.as_sql()],
        )?
    };
    if rows == 0 {
        return Err(VerbError::not_found_text(schema.name, id.as_string()));
    }
    Ok(json!({ "ok": true, "id": id.as_json() }))
}

fn has_archived_field(schema: &EntitySchema) -> bool {
    schema.fields.iter().any(|f| f.name == "archived")
}
