//! Subtasks and checklist management handlers

use crate::error::{ApiError, ApiResult};
use crate::models::{ChecklistItemDto, SubtaskTuple};
use crate::state::AppState;
use axum::{
    extract::{Path, State},
    http::StatusCode,
    Json,
};
use uuid::Uuid;

/// Get subtasks for a parent task
pub(crate) async fn get_subtasks(
    State(state): State<AppState>,
    Path(parent_task_id): Path<String>,
) -> ApiResult<Json<Vec<ChecklistItemDto>>> {
    // Query subtasks where parent_task_id matches
    let rows: Vec<SubtaskTuple> = sqlx::query_as(
        "SELECT id, project_id, task_id, description, phase, completed, completed_at, created_at
         FROM checklist_items WHERE parent_task_id = ?",
    )
    .bind(&parent_task_id)
    .fetch_all(state.db.pool())
    .await?;

    let dtos = rows
        .into_iter()
        .map(
            |(
                id,
                _project_id,
                task_id,
                description,
                _phase,
                completed,
                completed_at,
                created_at,
            )| {
                ChecklistItemDto {
                    id,
                    task_id,
                    description,
                    completed,
                    completed_at,
                    created_at,
                }
            },
        )
        .collect();

    Ok(Json(dtos))
}

/// Create a subtask under a parent task
pub(crate) async fn create_subtask(
    State(state): State<AppState>,
    Path(parent_task_id): Path<String>,
    Json(req): Json<serde_json::Value>,
) -> ApiResult<(StatusCode, Json<ChecklistItemDto>)> {
    // Verify parent task exists
    let parent_rows: Vec<(String, String)> =
        sqlx::query_as("SELECT id, project_id FROM checklist_items WHERE id = ?")
            .bind(&parent_task_id)
            .fetch_all(state.db.pool())
            .await?;

    if parent_rows.is_empty() {
        return Err(ApiError::NotFound(format!(
            "Parent task {} not found",
            parent_task_id
        )));
    }

    let project_id = &parent_rows[0].1;

    let description = req
        .get("description")
        .and_then(|v| v.as_str())
        .ok_or_else(|| ApiError::BadRequest("Missing 'description' field".to_string()))?;

    let task_id = req
        .get("task_id")
        .and_then(|v| v.as_str())
        .unwrap_or("subtask");

    // Create subtask
    let id = Uuid::new_v4().to_string();
    let now = chrono::Utc::now().to_rfc3339();

    sqlx::query(
        "INSERT INTO checklist_items (id, project_id, phase, task_id, description, completed, created_at, parent_task_id)
         VALUES (?, ?, ?, ?, ?, ?, ?, ?)"
    )
    .bind(&id)
    .bind(project_id)
    .bind("Creation")
    .bind(task_id)
    .bind(description)
    .bind(false)
    .bind(&now)
    .bind(&parent_task_id)
    .execute(state.db.pool())
    .await?;

    // Broadcast event
    state
        .events
        .broadcast(crate::websocket::ProjectEvent::TaskCreated {
            task_id: id.clone(),
            project_id: project_id.clone(),
            description: description.to_string(),
            timestamp: now.clone(),
        });

    let dto = ChecklistItemDto {
        id,
        task_id: task_id.to_string(),
        description: description.to_string(),
        completed: false,
        completed_at: None,
        created_at: now,
    };

    Ok((StatusCode::CREATED, Json(dto)))
}

/// Delete a subtask
pub(crate) async fn delete_subtask(
    State(state): State<AppState>,
    Path((parent_task_id, subtask_id)): Path<(String, String)>,
) -> ApiResult<StatusCode> {
    // Verify subtask belongs to parent
    let rows: Vec<(String,)> =
        sqlx::query_as("SELECT id FROM checklist_items WHERE id = ? AND parent_task_id = ?")
            .bind(&subtask_id)
            .bind(&parent_task_id)
            .fetch_all(state.db.pool())
            .await?;

    if rows.is_empty() {
        return Err(ApiError::NotFound(format!(
            "Subtask {} not found under parent {}",
            subtask_id, parent_task_id
        )));
    }

    sqlx::query("DELETE FROM checklist_items WHERE id = ?")
        .bind(&subtask_id)
        .execute(state.db.pool())
        .await?;

    Ok(StatusCode::NO_CONTENT)
}

/// Get task hierarchy (parent with all subtasks)
pub(crate) async fn get_task_hierarchy(
    State(state): State<AppState>,
    Path(task_id): Path<String>,
) -> ApiResult<Json<serde_json::Value>> {
    // Get parent task
    let parent: Option<(String, String, String, bool)> = sqlx::query_as(
        "SELECT id, task_id, description, completed FROM checklist_items WHERE id = ?",
    )
    .bind(&task_id)
    .fetch_optional(state.db.pool())
    .await?;

    if parent.is_none() {
        return Err(ApiError::NotFound(format!("Task {} not found", task_id)));
    }

    let (id, task_id_val, description, completed) = parent.unwrap();

    // Get subtasks
    let subtasks: Vec<(String, String, String, bool)> = sqlx::query_as(
        "SELECT id, task_id, description, completed FROM checklist_items WHERE parent_task_id = ?",
    )
    .bind(&task_id)
    .fetch_all(state.db.pool())
    .await?;

    let subtask_json: Vec<serde_json::Value> = subtasks
        .into_iter()
        .map(|(id, task_id, desc, comp)| {
            serde_json::json!({
                "id": id,
                "task_id": task_id,
                "description": desc,
                "completed": comp,
            })
        })
        .collect();

    Ok(Json(serde_json::json!({
        "id": id,
        "task_id": task_id_val,
        "description": description,
        "completed": completed,
        "subtasks": subtask_json,
        "subtask_count": subtask_json.len(),
    })))
}

#[cfg(test)]
#[allow(dead_code, unused_variables)]
mod tests {
    use syntaxis_core::SqliteDatabase;

    #[tokio::test]
    async fn test_subtask_creation() {
        // NOTE: Subtask hierarchy (parent_task_id) not yet in Database trait
        // This test is templated for future implementation
        let _db = SqliteDatabase::new(":memory:").await.unwrap();
        // When implemented, will test: subtask creation with parent references
    }

    #[tokio::test]
    async fn test_task_hierarchy() {
        // NOTE: Task hierarchy queries not yet supported in Database trait
        // This test is templated for future implementation
        let _db = SqliteDatabase::new(":memory:").await.unwrap();
        // When implemented, will test: fetching all subtasks for a parent task
    }
}
