//! Who API - 身份識別與 ID 映射接口 (Video-Scoped)

use axum::{
    extract::State,
    http::StatusCode,
    response::Json,
    routing::{get, post},
    Router,
};
use serde::{Deserialize, Serialize};

// --- Request / Response Structures ---

#[derive(Debug, Deserialize)]
pub struct WhoQuery {
    pub face_id: Option<String>,
    pub speaker_id: Option<String>,
    pub uuid: Option<String>,
    pub chunk_id: Option<String>,
}

#[derive(Debug, Deserialize)]
pub struct WhoCandidatesRequest {
    pub query: String,
    pub file_uuid: Option<String>,
    pub limit: Option<i32>,
}

#[derive(Debug, Deserialize)]
pub struct DefinePersonRequest {
    pub uuid: String,
    pub identity_id: Option<i32>,
    pub name: String,
    pub face_ids: Option<Vec<String>>,
    pub speaker_ids: Option<Vec<String>>,
}

#[derive(Debug, Serialize)]
pub struct WhoIdentity {
    pub identity_id: i32,
    pub uuid: String,
    pub name: String,
    pub tags: Option<Vec<String>>,
    pub face_ids: Vec<String>,
    pub speaker_ids: Vec<String>,
}

// --- API Handlers ---

/// GET /api/v1/who
pub async fn get_who_identity(
    State(state): State<crate::api::server::AppState>,
    axum::extract::Query(query): axum::extract::Query<WhoQuery>,
) -> Result<Json<serde_json::Value>, (StatusCode, Json<serde_json::Value>)> {
    let db = &state.db;

    // Priority 1: Query by Chunk (UUID + Chunk ID)
    if let (Some(uuid), Some(chunk_id)) = (&query.uuid, &query.chunk_id) {
        let info = db
            .get_who_info_by_chunk(uuid, chunk_id)
            .await
            .map_err(|e| {
                (
                    StatusCode::INTERNAL_SERVER_ERROR,
                    Json(serde_json::json!({ "error": e.to_string() })),
                )
            })?;
        return Ok(Json(info));
    }

    // Priority 2: List all for a specific UUID
    if let Some(uuid) = &query.uuid {
        // TODO: Implement list_all_persons(uuid)
        return Ok(Json(serde_json::json!({ "message": "List all pending" })));
    }

    Err((
        StatusCode::BAD_REQUEST,
        Json(serde_json::json!({ "error": "Missing uuid" })),
    ))
}

/// POST /api/v1/who/candidates
/// Search person_identities table for n8n workflow
pub async fn get_who_candidates(
    State(state): State<crate::api::server::AppState>,
    Json(req): Json<WhoCandidatesRequest>,
) -> Result<Json<serde_json::Value>, (StatusCode, Json<serde_json::Value>)> {
    let db = &state.db;
    let limit = req.limit.unwrap_or(20);
    let query_str = format!("%{}%", req.query);

    let results = db
        .search_person_candidates(&query_str, &req.file_uuid, limit)
        .await
        .map_err(|e| {
            (
                StatusCode::INTERNAL_SERVER_ERROR,
                Json(serde_json::json!({ "error": e.to_string() })),
            )
        })?;

    // Format for n8n
    let response = serde_json::json!({
        "query": req.query,
        "items": results,
        "total": results.len()
    });

    Ok(Json(response))
}

/// POST /api/v1/who
pub async fn define_person(
    State(state): State<crate::api::server::AppState>,
    Json(req): Json<DefinePersonRequest>,
) -> Result<Json<WhoIdentity>, (StatusCode, Json<serde_json::Value>)> {
    let db = &state.db;

    let identity = db
        .create_or_update_person(
            &req.uuid,
            req.identity_id,
            req.name.clone(),
            req.face_ids.unwrap_or_default(),
            req.speaker_ids.unwrap_or_default(),
        )
        .await
        .map_err(|e| {
            (
                StatusCode::INTERNAL_SERVER_ERROR,
                Json(serde_json::json!({ "error": e.to_string() })),
            )
        })?;

    Ok(Json(identity))
}

// --- Router Setup ---

pub fn who_routes() -> Router<crate::api::server::AppState> {
    Router::new()
        .route("/api/v1/who", get(get_who_identity).post(define_person))
        .route("/api/v1/who/candidates", post(get_who_candidates))
}
