use std::{ops::ControlFlow, path::Path};

use tokio::{fs::File, io::AsyncWriteExt, sync::Mutex as TokioMutex};
use tracing::{debug, error, warn};

use super::state::ReplContext;
use std::sync::Arc;

pub async fn handle_set_output(ctx: &mut ReplContext<'_>, file_path: &Path) -> ControlFlow<()> {
	let _ = handle_unset_output(ctx).await;

	if file_path.exists() {
		error!("File already exists: {file_path:?}");
		eprintln!("Error: File already exists: {}", file_path.display());
		return ControlFlow::Continue(());
	}

	match File::create(file_path).await {
		Ok(file) => {
			debug!("opened output file: {file_path:?}");
			eprintln!("Output will be written to: {file_path:?}");
			let mut state = ctx.repl_state.lock().unwrap();
			state.output_file = Some(Arc::new(TokioMutex::new(file)));
		}
		Err(e) => {
			error!("Failed to open output file '{file_path:?}': {e}");
		}
	}

	ControlFlow::Continue(())
}

pub async fn handle_unset_output(ctx: &mut ReplContext<'_>) -> ControlFlow<()> {
	let file_arc_opt = {
		let mut state = ctx.repl_state.lock().unwrap();
		state.output_file.take()
	};

	if let Some(file_arc) = file_arc_opt {
		let mut file = file_arc.lock().await;
		if let Err(e) = file.flush().await {
			warn!("failed to flush output file: {e}");
		}
		debug!("closed output file");
		eprintln!("Output redirection closed");
	}

	ControlFlow::Continue(())
}
