//! 工程依赖关系 — module_dependencies 表 CRUD(V35,工程间依赖边)
//!
//! 简化版:insert / delete / list_by_field(查 project_id)。

use std::sync::Arc;

use rusqlite::{params, Row};
use tokio::sync::Mutex;

use crate::db::Database;
use crate::models::ModuleDependencyRecord;

use super::{storage_err};

fn dep_from_row(row: &Row<'_>) -> std::result::Result<ModuleDependencyRecord, rusqlite::Error> {
    Ok(ModuleDependencyRecord {
        id: row.get("id")?,
        project_id: row.get("project_id")?,
        from_module_id: row.get("from_module_id")?,
        to_module_id: row.get("to_module_id")?,
        dep_type: row.get("dep_type")?,
        label: row.get("label")?,
        created_at: row.get("created_at")?,
    })
}

pub struct ModuleDependencyRepo {
    conn: Arc<Mutex<rusqlite::Connection>>,
}

impl ModuleDependencyRepo {
    pub fn new(db: &Database) -> Self {
        Self { conn: db.conn() }
    }

    pub async fn insert(&self, record: ModuleDependencyRecord) -> Result<bool, df_types::error::Error> {
        let conn = self.conn.clone();
        tokio::task::spawn_blocking(move || {
            let guard = conn.blocking_lock();
            let r = &record;
            let affected = guard
                .execute(
                    "INSERT INTO module_dependencies \
                     (id, project_id, from_module_id, to_module_id, dep_type, label, created_at) \
                     VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)",
                    params![
                        r.id, r.project_id, r.from_module_id, r.to_module_id,
                        r.dep_type, r.label, r.created_at,
                    ],
                )
                .map_err(storage_err)?;
            Ok(affected > 0)
        })
        .await
        .map_err(storage_err)?
    }

    pub async fn delete(&self, id: &str) -> Result<bool, df_types::error::Error> {
        let conn = self.conn.clone();
        let id = id.to_owned();
        tokio::task::spawn_blocking(move || {
            let guard = conn.blocking_lock();
            let affected = guard
                .execute("DELETE FROM module_dependencies WHERE id = ?1", params![id])
                .map_err(storage_err)?;
            Ok(affected > 0)
        })
        .await
        .map_err(storage_err)?
    }

    pub async fn list_by_field(&self, field: &str, value: &str) -> Result<Vec<ModuleDependencyRecord>, df_types::error::Error> {
        let conn = self.conn.clone();
        let field = field.to_owned();
        let value = value.to_owned();
        tokio::task::spawn_blocking(move || {
            let guard = conn.blocking_lock();
            let sql = format!(
                "SELECT id, project_id, from_module_id, to_module_id, dep_type, label, created_at \
                 FROM module_dependencies WHERE {field} = ?1 ORDER BY created_at ASC"
            );
            let mut stmt = guard.prepare(&sql).map_err(storage_err)?;
            let rows = stmt
                .query_map(params![value], dep_from_row)
                .map_err(storage_err)?;
            let mut results = Vec::new();
            for r in rows {
                results.push(r.map_err(storage_err)?);
            }
            Ok(results)
        })
        .await
        .map_err(storage_err)?
    }
}
