use std::fs;
use std::path::PathBuf;

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

#[derive(Debug, Clone, serde::Deserialize)]
#[allow(dead_code)]
pub struct AsrData {
    #[serde(default)]
    pub segments: Vec<AsrSegment>,
}

#[allow(dead_code)]
pub struct AsrOverlay {
    segments: Vec<AsrSegment>,
    current_text: String,
}

#[allow(dead_code)]
impl AsrOverlay {
    pub fn new() -> Self {
        Self {
            segments: Vec::new(),
            current_text: String::new(),
        }
    }

    pub fn load_from_file(&mut self, video_path: &str) -> bool {
        // Try to find ASR JSON file in various locations
        let video_dir = PathBuf::from(video_path).parent().map(|p| p.to_path_buf());
        let _video_stem = PathBuf::from(video_path)
            .file_stem()
            .and_then(|s| s.to_str())
            .unwrap_or("");

        let mut paths = Vec::new();

        // In same directory as video
        if let Some(_dir) = &video_dir {
            paths.push(PathBuf::from(video_path).with_extension("asr.json"));
        }

        // In data directory
        let data_dir = PathBuf::from("/Users/accusys/momentry_core_0.1");
        if let Ok(content) = fs::read_to_string(video_path) {
            let _ = content;
        }

        // Try probe file for UUID
        let uuid = self
            .find_uuid_from_probe(video_path)
            .or_else(|| lookup_uuid_from_db(video_path));

        if let Some(uuid_val) = uuid {
            paths.push(data_dir.join(format!("{}.asr.json", uuid_val)));
        }

        for path in &paths {
            if path.exists() {
                if let Ok(content) = fs::read_to_string(path) {
                    if let Ok(data) = serde_json::from_str::<AsrData>(&content) {
                        self.segments = data.segments;
                        println!(
                            "Loaded {} ASR segments from {:?}",
                            self.segments.len(),
                            path
                        );
                        return true;
                    }
                }
            }
        }

        // Try to load from PostgreSQL
        if let Some(uuid) = lookup_uuid_from_db(video_path) {
            let db_path = PathBuf::from("/Users/accusys/momentry_core_0.1")
                .join(format!("{}.asr.json", uuid));
            if db_path.exists() {
                if let Ok(content) = fs::read_to_string(&db_path) {
                    if let Ok(data) = serde_json::from_str::<AsrData>(&content) {
                        self.segments = data.segments;
                        println!(
                            "Loaded {} ASR segments from database file",
                            self.segments.len()
                        );
                        return true;
                    }
                }
            }
        }

        false
    }

    #[allow(dead_code)]
    pub fn update(&mut self, current_time: f64) {
        self.current_text = String::new();

        for segment in &self.segments {
            if current_time >= segment.start && current_time <= segment.end {
                self.current_text = segment.text.clone();
                break;
            }
        }
    }

    #[allow(dead_code)]
    pub fn get_text(&self) -> &str {
        &self.current_text
    }

    #[allow(dead_code)]
    pub fn is_empty(&self) -> bool {
        self.segments.is_empty()
    }

    #[allow(dead_code)]
    fn find_uuid_from_probe(&self, video_path: &str) -> Option<String> {
        let path_buf = PathBuf::from(video_path);
        let video_stem = path_buf.file_stem().and_then(|s| s.to_str()).unwrap_or("");

        let probe_path = PathBuf::from("/Users/accusys/momentry_core_0.1")
            .join(format!("{}.probe.json", video_stem));

        if probe_path.exists() {
            if let Ok(content) = fs::read_to_string(&probe_path) {
                if let Ok(probe) = serde_json::from_str::<serde_json::Value>(&content) {
                    return probe
                        .get("uuid")
                        .and_then(|v| v.as_str())
                        .map(|s| s.to_string());
                }
            }
        }
        None
    }
}

#[allow(dead_code)]
fn lookup_uuid_from_db(video_path: &str) -> Option<String> {
    use std::process::Command as StdCommand;

    let filename = std::path::Path::new(video_path)
        .file_stem()
        .and_then(|s| s.to_str())
        .unwrap_or("");

    let output = StdCommand::new("psql")
        .args([
            "-U",
            "accusys",
            "-h",
            "localhost",
            "-d",
            "momentry",
            "-t",
            "-A",
            "-c",
            &format!(
                "SELECT uuid FROM videos WHERE file_path LIKE '%{}%' LIMIT 1",
                filename
            ),
        ])
        .output()
        .ok()?;

    if output.status.success() {
        let uuid = String::from_utf8_lossy(&output.stdout).trim().to_string();
        if !uuid.is_empty() {
            return Some(uuid);
        }
    }

    None
}
