// TTS-dispatcher — delegerer til synops-tts CLI.
//
// Maskinrommet beholder: voice_id-oppslag (payload > node metadata > env).
// Alt annet (ElevenLabs-kall, CAS-lagring, PG-skriving) gjøres av synops-tts.
// PG NOTIFY-triggere sender sanntidsoppdateringer.
//
// Jobbtype: "tts_generate"
// Payload: { "text", "voice_id"?, "language"?, "source_node_id"?, "requested_by" }
//
// Ref: docs/retninger/unix_filosofi.md, docs/proposals/ghost_host_tts.md

use sqlx::PgPool;
use uuid::Uuid;

use crate::cli_dispatch;
use crate::jobs::JobRow;

/// Synops-tts binary path.
fn tts_bin() -> String {
    std::env::var("SYNOPS_TTS_BIN")
        .unwrap_or_else(|_| "synops-tts".to_string())
}

/// Håndterer tts_generate-jobb.
///
/// Spawner synops-tts med --write for å gjøre alt arbeidet:
/// ElevenLabs-kall, CAS-lagring, PG-skriving, ressurslogging.
/// PG NOTIFY-triggere sender sanntidsoppdateringer til klienter.
pub async fn handle_tts_job(
    job: &JobRow,
    db: &PgPool,
) -> Result<serde_json::Value, String> {
    let text = job.payload["text"]
        .as_str()
        .ok_or("Mangler 'text' i payload")?;

    let source_node_id: Option<Uuid> = job.payload["source_node_id"]
        .as_str()
        .and_then(|s| s.parse().ok());

    let requested_by: Uuid = job.payload["requested_by"]
        .as_str()
        .and_then(|s| s.parse().ok())
        .ok_or("Mangler gyldig 'requested_by' i payload")?;

    let language = job.payload["language"]
        .as_str()
        .unwrap_or("no");

    // Bestem voice_id: payload > source-node metadata > env default
    let voice_id = resolve_voice_id(job, db, source_node_id).await?;

    // Bygg kommando
    let bin = tts_bin();
    let mut cmd = tokio::process::Command::new(&bin);

    cmd.arg("--text").arg(text)
        .arg("--voice").arg(&voice_id)
        .arg("--language").arg(language)
        .arg("--requested-by").arg(requested_by.to_string())
        .arg("--write");

    if let Some(source_id) = source_node_id {
        cmd.arg("--source-node-id").arg(source_id.to_string());
    }

    // Sett miljøvariabler CLI-verktøyet trenger
    cli_dispatch::set_database_url(&mut cmd)?;
    cli_dispatch::forward_env(&mut cmd, "CAS_ROOT");
    cli_dispatch::forward_env(&mut cmd, "ELEVENLABS_API_KEY");
    cli_dispatch::forward_env(&mut cmd, "ELEVENLABS_MODEL");
    cli_dispatch::forward_env(&mut cmd, "ELEVENLABS_DEFAULT_VOICE");

    tracing::info!(
        text_len = text.len(),
        voice_id = %voice_id,
        bin = %bin,
        "Starter synops-tts"
    );

    let result = cli_dispatch::run_cli_tool(&bin, &mut cmd).await?;

    // PG-skriving gjøres av synops-tts med --write.
    // PG NOTIFY-triggere sender sanntidsoppdateringer til WebSocket-klienter.

    tracing::info!(
        cas_hash = result["cas_hash"].as_str().unwrap_or("n/a"),
        media_node_id = result["media_node_id"].as_str().unwrap_or("n/a"),
        "synops-tts fullført"
    );

    Ok(result)
}

/// Bestem voice_id: payload-verdi > source-node metadata.voice_preference > env default.
async fn resolve_voice_id(
    job: &JobRow,
    db: &PgPool,
    source_node_id: Option<Uuid>,
) -> Result<String, String> {
    // 1. Eksplisitt i payload
    if let Some(vid) = job.payload["voice_id"].as_str() {
        if !vid.is_empty() {
            return Ok(vid.to_string());
        }
    }

    // 2. Source-nodens metadata.voice_preference.voice_id
    if let Some(node_id) = source_node_id {
        let meta: Option<serde_json::Value> = sqlx::query_scalar(
            "SELECT metadata FROM nodes WHERE id = $1",
        )
        .bind(node_id)
        .fetch_optional(db)
        .await
        .map_err(|e| format!("PG-feil ved henting av voice_preference: {e}"))?
        .flatten();

        if let Some(meta) = meta {
            if let Some(vid) = meta
                .get("voice_preference")
                .and_then(|vp| vp.get("voice_id"))
                .and_then(|v| v.as_str())
            {
                if !vid.is_empty() {
                    tracing::info!(node_id = %node_id, voice_id = %vid, "Bruker mottaker-preferanse");
                    return Ok(vid.to_string());
                }
            }
        }
    }

    // 3. Miljøvariabel-default
    Ok(std::env::var("ELEVENLABS_DEFAULT_VOICE")
        .unwrap_or_else(|_| "21m00Tcm4TlvDq8ikWAM".to_string()))
}

