// Tauri commands for human-in-the-loop feedback capture and retrieval.
// Phase 2 of the feature-complete roadmap: thumbs + correction capture
// on AI-generated output feeds a few-shot loop that conditions future
// prompts on the user's preferred style.

use serde::Deserialize;

use lumotia_storage::{
    record_feedback as db_record_feedback, FeedbackTargetType, RecordFeedbackParams,
};

use crate::AppState;

#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RecordFeedbackInput {
    /// One of "microstep", "task_extraction", "cleanup".
    pub target_type: String,
    /// Optional surface-specific id (subtask id, task id, transcript id).
    #[serde(default)]
    pub target_id: Option<String>,
    /// -1 = thumbs down, 0 = correction (neutral), +1 = thumbs up.
    pub rating: i8,
    #[serde(default)]
    pub original_text: Option<String>,
    #[serde(default)]
    pub corrected_text: Option<String>,
    /// Freeform JSON context: e.g. the parent task text, the transcript
    /// chunk the AI was given, etc. Used later by the prompt builder
    /// to reconstruct the (input, preferred-output) pair.
    #[serde(default)]
    pub context_json: Option<String>,
    #[serde(default)]
    pub profile_id: Option<String>,
}

fn parse_target_type(raw: &str) -> Result<FeedbackTargetType, String> {
    FeedbackTargetType::parse(raw).ok_or_else(|| format!("unknown feedback target_type: {raw}"))
}

#[tauri::command]
pub async fn record_feedback(
    state: tauri::State<'_, AppState>,
    input: RecordFeedbackInput,
) -> Result<i64, String> {
    let target_type = parse_target_type(&input.target_type)?;
    db_record_feedback(
        &state.db,
        RecordFeedbackParams {
            target_type,
            target_id: input.target_id,
            rating: input.rating,
            original_text: input.original_text,
            corrected_text: input.corrected_text,
            context_json: input.context_json,
            profile_id: input.profile_id,
        },
    )
    .await
    .map_err(|e| e.to_string())
}
