//! Routes API pour l'encodage audio
//!
//! Ce module fournit les endpoints REST pour :
//! - Lancer un encodage (POST /admin/stream/encode/:track_id)
//! - Vérifier le statut (GET /admin/stream/status/:track_id)
//! - Récupérer la playlist HLS (GET /stream/:track_id/:quality/index.m3u8)
//! - Récupérer un segment (GET /stream/:track_id/:quality/segment_*.ts)

use crate::core::encoding_service::EncodingService;
use crate::error::{AppError, Result};
use axum::{
    extract::{Path, State},
    http::{header, StatusCode},
    response::{IntoResponse, Response},
    Json,
};
use serde::{Deserialize, Serialize};
use uuid::Uuid;

/// POST /admin/stream/encode/:track_id
/// Lance un encodage pour un track avec une qualité spécifique
pub async fn encode_track_handler(
    Path((track_id, quality)): Path<(Uuid, String)>,
    State(encoding_service): State<EncodingService>,
) -> Result<Json<EncodeResponse>> {
    // Valider la qualité
    if !["low", "medium", "high", "hi_res"].contains(&quality.as_str()) {
        return Err(AppError::InvalidData {
            message: format!("Invalid quality: {}. Must be one of: low, medium, high, hi_res", quality),
        });
    }

    encoding_service
        .encode_track(track_id, &quality)
        .await?;

    Ok(Json(EncodeResponse {
        success: true,
        message: format!("Encoding started for track {} with quality {}", track_id, quality),
        track_id,
        quality,
    }))
}

/// POST /admin/stream/encode/:track_id/all
/// Lance l'encodage pour toutes les qualités d'un track
pub async fn encode_track_all_qualities_handler(
    Path(track_id): Path<Uuid>,
    State(encoding_service): State<EncodingService>,
) -> Result<Json<EncodeResponse>> {
    encoding_service
        .encode_track_all_qualities(track_id)
        .await?;

    Ok(Json(EncodeResponse {
        success: true,
        message: format!("Encoding started for all qualities for track {}", track_id),
        track_id,
        quality: "all".to_string(),
    }))
}

/// GET /admin/stream/status/:track_id
/// Récupère le statut d'encodage pour un track
pub async fn get_encoding_status_handler(
    Path(track_id): Path<Uuid>,
    State(encoding_service): State<EncodingService>,
) -> Result<Json<EncodingStatusResponse>> {
    let statuses = encoding_service
        .get_encoding_status(track_id)
        .await?;

    Ok(Json(EncodingStatusResponse {
        track_id,
        statuses,
    }))
}

/// GET /stream/:track_id/:quality/index.m3u8
/// Sert la playlist HLS pour un track et une qualité
pub async fn serve_hls_manifest_handler(
    Path((track_id, quality)): Path<(Uuid, String)>,
    State(encoding_service): State<EncodingService>,
) -> Result<Response> {
    use std::path::PathBuf;
    use crate::core::encoding_service::EncodingService;

    // Construire le chemin du manifest
    // Note: On suppose que le base_output_dir est configuré dans EncodingService
    // Pour l'instant, on utilise un chemin par défaut
    let base_dir = std::env::var("STREAM_OUTPUT_DIR")
        .unwrap_or_else(|_| "/data/streams".to_string());
    
    let manifest_path = PathBuf::from(base_dir)
        .join(track_id.to_string())
        .join(&quality)
        .join("index.m3u8");

    if !manifest_path.exists() {
        return Err(AppError::NotFound {
            resource: format!("HLS manifest for track {} quality {}", track_id, quality),
        });
    }

    let content = tokio::fs::read_to_string(&manifest_path)
        .await
        .map_err(|e| AppError::InternalError {
            message: format!("Failed to read HLS manifest: {}", e),
        })?;

    Ok(Response::builder()
        .status(StatusCode::OK)
        .header(header::CONTENT_TYPE, "application/vnd.apple.mpegurl")
        .header(header::CACHE_CONTROL, "public, max-age=3600")
        .body(content.into())
        .map_err(|e| AppError::InternalError {
            message: format!("Failed to create response: {}", e),
        })?)
}

/// GET /stream/:track_id/:quality/segment_*.ts
/// Sert un segment HLS
pub async fn serve_hls_segment_handler(
    Path((track_id, quality, segment_name)): Path<(Uuid, String, String)>,
) -> Result<Response> {
    use std::path::PathBuf;

    // Valider le nom du segment (sécurité)
    if !segment_name.ends_with(".ts") {
        return Err(AppError::InvalidData {
            message: "Invalid segment name. Must end with .ts".to_string(),
        });
    }

    // Construire le chemin du segment
    let base_dir = std::env::var("STREAM_OUTPUT_DIR")
        .unwrap_or_else(|_| "/data/streams".to_string());
    
    let segment_path = PathBuf::from(base_dir)
        .join(track_id.to_string())
        .join(&quality)
        .join(&segment_name);

    if !segment_path.exists() {
        return Err(AppError::NotFound {
            resource: format!("HLS segment {} for track {} quality {}", segment_name, track_id, quality),
        });
    }

    // Lire le segment
    let content = tokio::fs::read(&segment_path)
        .await
        .map_err(|e| AppError::InternalError {
            message: format!("Failed to read HLS segment: {}", e),
        })?;

    Ok(Response::builder()
        .status(StatusCode::OK)
        .header(header::CONTENT_TYPE, "video/mp2t")
        .header(header::CACHE_CONTROL, "public, max-age=86400")
        .header(header::ACCEPT_RANGES, "bytes")
        .body(content.into())
        .map_err(|e| AppError::InternalError {
            message: format!("Failed to create response: {}", e),
        })?)
}

/// Réponse pour l'encodage
#[derive(Debug, Serialize)]
pub struct EncodeResponse {
    pub success: bool,
    pub message: String,
    pub track_id: Uuid,
    pub quality: String,
}

/// Réponse pour le statut d'encodage
#[derive(Debug, Serialize)]
pub struct EncodingStatusResponse {
    pub track_id: Uuid,
    pub statuses: Vec<crate::core::encoding_service::QualityStatus>,
}

