use super::exec::execute_command_internal;
use super::super::error::BtrfsError;
use crate::process::CommandResult;
use serde::Deserialize;
use std::path::PathBuf;

pub fn execute(device: &str) -> Result<CommandResult, BtrfsError> {
    execute_command_internal("lsblk", &["-J", "-fs", device])
}

#[derive(Debug, Clone)]
pub struct LsblkDeviceInfo {
    pub name: String,
    pub label: Option<String>,
    pub uuid: Option<String>,
    pub mount_path: Option<PathBuf>,
}

#[derive(Debug, Deserialize)]
struct LsblkResponse {
    blockdevices: Vec<BlockDevice>,
}

#[derive(Debug, Deserialize)]
struct BlockDevice {
    #[serde(default)]
    name: String,
    #[serde(default)]
    fstype: Option<String>,
    #[serde(default)]
    label: Option<String>,
    #[serde(default)]
    uuid: Option<String>,
    #[serde(default)]
    mountpoints: Option<Vec<Option<String>>>,
}

pub fn parse(output: &str) -> Result<Option<LsblkDeviceInfo>, BtrfsError> {
    let response: LsblkResponse = serde_json::from_str(output)
        .map_err(|e| BtrfsError::ParseError(format!("Failed to parse lsblk JSON output: {}", e)))?;

    if let Some(device) = response.blockdevices.first() {
        if device.fstype.as_deref() == Some("btrfs") {
            let label = device.label.clone().filter(|l| !l.is_empty() && l != "none");
            let uuid = device.uuid.clone();
            let mount_path = device.mountpoints.as_ref()
                .and_then(|mountpoints| {
                    mountpoints.iter()
                        .find_map(|mp| mp.as_ref())
                        .map(|mp| PathBuf::from(mp))
                });
            
            return Ok(Some(LsblkDeviceInfo {
                name: device.name.clone(),
                label,
                uuid,
                mount_path,
            }));
        }
    }
    
    Ok(None)
}

pub fn execute_and_parse(device: &str) -> Result<Option<LsblkDeviceInfo>, BtrfsError> {
    let result = execute(device)?;
    parse(&result.stdout)
}

