use crate::transcoding::pipeline::{
    job::{TranscodingJob, JobPriority},
    queue::PriorityQueue,
    worker::TranscodingWorker,
    job_manager::JobManager,
};
use std::sync::Arc;
use std::path::PathBuf;
use crate::transcoding::codecs::profiles::QualityProfile;

#[derive(Clone)]
pub struct TranscodingEngine {
    queue: Arc<PriorityQueue>,
    job_manager: Arc<JobManager>,
    worker_count: usize,
}

impl TranscodingEngine {
    pub fn new(worker_count: usize) -> Self {
        let queue = Arc::new(PriorityQueue::new(1000)); // Capacité 1000
        let job_manager = Arc::new(JobManager::new());
        
        Self {
            queue,
            job_manager,
            worker_count,
        }
    }

    /// Récupère le JobManager pour accès externe
    pub fn job_manager(&self) -> Arc<JobManager> {
        self.job_manager.clone()
    }

    /// Démarre les workers en arrière-plan
    pub fn start(&self) {
        for id in 0..self.worker_count {
            let queue = self.queue.clone();
            let job_manager = self.job_manager.clone();
            let worker = TranscodingWorker::new(id);
            
            tokio::spawn(async move {
                tracing::info!("Transcoding Worker {} started", id);
                loop {
                    // Attente bloquante (async) du prochain job
                    if let Some(job) = queue.next_job().await {
                        let job_id = job.id;
                        // Traiter le job
                        let result_job = worker.process(job).await;
                        // Mettre à jour le JobManager avec le résultat
                        if let Err(e) = job_manager.update_job(result_job).await {
                            tracing::error!("Worker {} failed to update job {}: {}", id, job_id, e);
                        }
                    } else {
                        // Si None, la queue est fermée/détruite
                        break;
                    }
                }
                tracing::info!("Transcoding Worker {} stopped", id);
            });
        }
    }

    /// Soumet un nouveau job de transcodage
    pub async fn submit(
        &self,
        track_id: String,
        input_path: PathBuf,
        output_dir: PathBuf,
        profile: QualityProfile,
        priority: JobPriority
    ) -> Result<uuid::Uuid, String> {
        let job = TranscodingJob::new(
            track_id,
            input_path,
            output_dir,
            profile,
            priority
        );
        let job_id = job.id;

        // Enregistrer le job dans le JobManager
        self.job_manager.enqueue(job.clone()).await;
        
        // Soumettre à la queue
        self.queue.submit(job).await.map_err(|e| e.to_string())?;
        
        tracing::info!(job_id = %job_id, "Job submitted to transcoding engine");
        Ok(job_id)
    }
}
