use journal::{
	journal::JournalType,
	types::{
		format_dose, Consumer, Dose, Ingestion, IngestionKind, IngestionKinds, Session,
		SubstanceIngestion, SustenanceIngestion,
	},
};

use crate::formatting::{format_ingestion_time, format_substance_ingestion_roa};

fn print_substance_ingestion(
	journal: &JournalType,
	ingestion: &Ingestion,
	substance_ingestion: &SubstanceIngestion,
) {
	let unit = journal.resolve_substance_unit(substance_ingestion).unwrap();

	println!(
		"Substance|{}|{}|{}|{}|{}",
		substance_ingestion.substance_name,
		format_dose(&substance_ingestion.dose, &unit),
		format_substance_ingestion_roa(substance_ingestion, &unit),
		ingestion.consumer,
		format_ingestion_time(ingestion)
	)
}

fn print_sustenance_ingestion(
	journal: &JournalType,
	ingestion: &Ingestion,
	sustenance_ingestion: &SustenanceIngestion,
) {
	let sustenance = journal
		.get_sustenance(&sustenance_ingestion.sustenance_id)
		.unwrap();

	println!(
		"Sustenance|{}|{} {}|{}|{}",
		sustenance.name,
		sustenance_ingestion.amount,
		sustenance.unit,
		ingestion.consumer,
		format_ingestion_time(ingestion)
	)
}

pub fn calculate_ingestion_kinds(kind: &mut IngestionKinds) {
	//println!("{kind:#?}");

	if let IngestionKind::Sustenance(sustenance) = &kind.ingestion {
		for kinds in kind.includes.iter_mut() {
			match &mut kinds.ingestion {
				IngestionKind::Substance(ingestion) => {
					ingestion.dose = Dose::new_precise(sustenance.amount) * ingestion.dose.clone();
				}
				IngestionKind::Sustenance(ingestion) => {
					ingestion.amount *= sustenance.amount;

					calculate_ingestion_kinds(kinds)
				}
				IngestionKind::Hydration { amount } => {
					*amount = (sustenance.amount * *amount as f64).round() as u64
				}
				_ => {}
			}
		}
	}
}

pub fn print_ingestion_kinds(
	journal: &JournalType,
	ingestion: &Ingestion,
	kinds: &IngestionKinds,
	depth: u64,
) {
	for _ in 0..(depth) {
		print!(" ");
	}
	if depth > 0 {
		print!("- ");
	}

	match &kinds.ingestion {
		IngestionKind::Unknown => {}
		IngestionKind::Substance(substance_ingestion) => {
			print_substance_ingestion(journal, ingestion, substance_ingestion);
		}
		IngestionKind::Sustenance(sustenance_ingestion) => {
			print_sustenance_ingestion(journal, ingestion, sustenance_ingestion);
		}
		IngestionKind::Hydration { amount } => {
			println!(
				"Hydration|{} ml|{}|{}",
				amount,
				ingestion.consumer,
				format_ingestion_time(ingestion)
			)
		}
	}

	for kinds in &kinds.includes {
		print_ingestion_kinds(journal, ingestion, kinds, depth + 1);
	}
}

pub fn print_ingestion_log(
	journal: &JournalType,
	session: &Session,
	consumer_filter: Option<&Vec<Consumer>>,
) {
	let ingestions = journal
		.get_session_ingestions(session.id)
		.expect("could not find ingestions for session");

	for ingestion in ingestions.iter() {
		if let Some(consumer_filter) = consumer_filter {
			if !consumer_filter.contains(&ingestion.consumer) {
				continue;
			}
		}

		let ingestion_kinds = journal
			.resolve_ingestion_kind(&ingestion.kind, true)
			.unwrap();
		println!("{ingestion_kinds:#?}");

		print_ingestion_kinds(journal, ingestion, &ingestion_kinds, 0)
	}
}