use super::exec::execute_btrfs_command;
use super::super::error::BtrfsError;
use super::super::types::FilesystemUsageStructured;
use crate::process::CommandResult;
use serde::Deserialize;

pub fn execute(path: &str) -> Result<CommandResult, BtrfsError> {
    let mut args = Vec::new();
    args.push("--format");
    args.push("json");
    args.push("filesystem");
    args.push("df");
    args.push("--raw");
    args.push(path);
    execute_btrfs_command(&args)
}

#[derive(Debug, Deserialize)]
pub struct FilesystemDfResponse {
    #[serde(rename = "filesystem-df")]
    pub filesystem_df: Vec<BlockGroupEntry>,
    // Ignore __header field if present
    #[serde(rename = "__header", default, skip_serializing)]
    _header: Option<serde_json::Value>,
}

#[derive(Debug, Clone, Deserialize)]
pub struct BlockGroupEntry {
    #[serde(rename = "bg-type")]
    pub bg_type: String,
    #[serde(rename = "bg-profile")]
    pub bg_profile: String,
    pub total: u64,
    pub used: u64,
}

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

    // Initialize default values
    let mut data = super::super::types::GroupUsage { profile: String::new(), total: 0, used: 0 };
    let mut metadata = super::super::types::GroupUsage { profile: String::new(), total: 0, used: 0 };
    let mut system = super::super::types::GroupUsage { profile: String::new(), total: 0, used: 0 };
    let mut globalreserved = super::super::types::GroupUsage { profile: String::new(), total: 0, used: 0 };

    for bg in response.filesystem_df {
        match bg.bg_type.as_str() {
            "Data" => {
                data.total += bg.total;
                data.used += bg.used;
                data.profile = bg.bg_profile;
            }
            "Metadata" => {
                metadata.total += bg.total;
                metadata.used += bg.used;
                metadata.profile = bg.bg_profile;
            }
            "System" => {
                system.total += bg.total;
                system.used += bg.used;
                system.profile = bg.bg_profile;
            }
            "GlobalReserve" => {
                globalreserved.total += bg.total;
                globalreserved.used += bg.used;
                globalreserved.profile = bg.bg_profile;
            }
            _ => {}
        }
    }

    Ok(FilesystemUsageStructured {
        data,
        metadata,
        system,
        globalreserved,
    })
}

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

