use anyhow::{Context, Result};
use serde::{Deserialize, Serialize};
use std::time::Duration;

use super::executor::PythonExecutor;

const ASR_TIMEOUT: Duration = Duration::from_secs(1800); // 30 minutes

#[derive(Debug, Serialize, Deserialize)]
pub struct AsrResult {
    pub language: Option<String>,
    pub language_probability: Option<f64>,
    pub segments: Vec<AsrSegment>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct AsrSegment {
    pub start: f64,
    pub end: f64,
    pub text: String,
}

pub async fn process_asr(
    video_path: &str,
    output_path: &str,
    uuid: Option<&str>,
) -> Result<AsrResult> {
    let executor = PythonExecutor::new()?;
    let script_path = executor.script_path("asr_processor.py");

    tracing::info!("[ASR] Starting ASR processing: {}", video_path);

    executor
        .run(
            "asr_processor.py",
            &[video_path, output_path],
            uuid,
            "ASR",
            Some(ASR_TIMEOUT),
        )
        .await
        .with_context(|| format!("Failed to run {:?}", script_path))?;

    let json_str = std::fs::read_to_string(output_path).context("Failed to read ASR output")?;

    let result: AsrResult =
        serde_json::from_str(&json_str).context("Failed to parse ASR output")?;

    tracing::info!(
        "[ASR] Result: {} segments, language: {:?}",
        result.segments.len(),
        result.language
    );

    Ok(result)
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_asr_result_serialization() {
        let result = AsrResult {
            language: Some("en".to_string()),
            language_probability: Some(0.95),
            segments: vec![
                AsrSegment {
                    start: 0.0,
                    end: 2.5,
                    text: "Hello world".to_string(),
                },
                AsrSegment {
                    start: 2.5,
                    end: 5.0,
                    text: "Test speech".to_string(),
                },
            ],
        };

        let json = serde_json::to_string(&result).unwrap();
        assert!(json.contains("Hello world"));
        assert!(json.contains("en"));
    }

    #[test]
    fn test_asr_result_deserialization() {
        let json = r#"{
            "language": "zh",
            "language_probability": 0.98,
            "segments": [
                {"start": 0.0, "end": 1.5, "text": "測試"}
            ]
        }"#;

        let result: AsrResult = serde_json::from_str(json).unwrap();
        assert_eq!(result.language, Some("zh".to_string()));
        assert_eq!(result.language_probability, Some(0.98));
        assert_eq!(result.segments.len(), 1);
        assert_eq!(result.segments[0].text, "測試");
    }

    #[test]
    fn test_asr_segment_default() {
        let segment = AsrSegment {
            start: 0.0,
            end: 1.0,
            text: String::new(),
        };
        assert_eq!(segment.start, 0.0);
        assert_eq!(segment.end, 1.0);
        assert!(segment.text.is_empty());
    }

    #[test]
    fn test_asr_result_empty_segments() {
        let result = AsrResult {
            language: None,
            language_probability: None,
            segments: vec![],
        };
        assert!(result.language.is_none());
        assert!(result.segments.is_empty());
    }
}
