// SPDX-FileCopyrightText: Copyright 2026 Daniel Hast
//
// SPDX-License-Identifier: Apache-2.0 OR MIT

use std::path::PathBuf;

use tracing::debug;

use crate::{
    client::{InputSource, OutputDestination},
    daemon::BrewInterfaceProxy,
    error::Result,
    io_handles::IoHandles,
};
use brew_proxy_utils::bundle::{Brewfile, BundleCommandLine, BundleSubcommand, IoDirection};

const DEFAULT_BREWFILE_PATH: &str = "Brewfile";

/// `brew bundle` needs special handling because it expects to read a Brewfile that the sandboxed
/// `brew` might not be able to access. We work around this by modifying the arguments to `brew
/// bundle` to read from standard input, and pass the Brewfile as a file descriptor.
pub async fn run_brew_bundle(
    proxy: &BrewInterfaceProxy<'_>,
    args: Vec<String>,
    interactive_auth: bool,
) -> Result<(IoHandles, u32, InputSource, OutputDestination)> {
    let bundle_cmd_line = BundleCommandLine::from_args(args)?;
    debug!("brew bundle subcommand: {bundle_cmd_line:?}");
    let subcommand = bundle_cmd_line.subcommand();
    let (modified_args, brewfile) = bundle_cmd_line.into_args_and_brewfile();

    let (io_serial, pid) = proxy.Bundle(modified_args, true, interactive_auth).await?;
    let io_handles = IoHandles::from(io_serial);
    let input_src = get_input_source(&brewfile, subcommand);
    let output_dest = get_output_dest(&brewfile, subcommand);
    Ok((io_handles, pid, input_src, output_dest))
}

fn get_input_source(brewfile: &Brewfile, subcommand: BundleSubcommand) -> InputSource {
    if !matches!(
        subcommand.io_direction(),
        IoDirection::Read | IoDirection::ReadWrite
    ) {
        return InputSource::Null;
    }
    match brewfile {
        Brewfile::Default => InputSource::Path(PathBuf::from(DEFAULT_BREWFILE_PATH)),
        Brewfile::Global => InputSource::Null,
        Brewfile::Stdin => InputSource::Stdin,
        Brewfile::Path(path) => InputSource::Path(path.clone()),
    }
}

fn get_output_dest(brewfile: &Brewfile, subcommand: BundleSubcommand) -> OutputDestination {
    if !matches!(
        subcommand.io_direction(),
        IoDirection::Write | IoDirection::ReadWrite
    ) {
        return OutputDestination::Stdout;
    }
    match brewfile {
        Brewfile::Global | Brewfile::Stdin => OutputDestination::Stdout,
        Brewfile::Default => OutputDestination::Path(PathBuf::from(DEFAULT_BREWFILE_PATH)),
        Brewfile::Path(path) => OutputDestination::Path(path.clone()),
    }
}
