use std::{fmt::Display, path::PathBuf};

use serde::Deserialize;

#[derive(Debug, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
#[serde(rename_all = "lowercase")]
pub enum IngredientGroup {
	Meat,
	Seafood,
	Vegetable,
	Mushroom,
	Herb,
	Fruit,
	Other,
	Special,
}

impl Display for IngredientGroup {
	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
		let str = match self {
			IngredientGroup::Meat => "Meat",
			IngredientGroup::Seafood => "Seafood",
			IngredientGroup::Vegetable => "Vegetable",
			IngredientGroup::Mushroom => "Mushroom",
			IngredientGroup::Herb => "Herb",
			IngredientGroup::Fruit => "Fruit",
			IngredientGroup::Other => "Other",
			IngredientGroup::Special => "Special",
		};

		f.write_str(str)
	}
}

#[derive(Debug, Deserialize, PartialEq, Eq)]
pub struct Ingredient {
	pub name: String,
	pub group: IngredientGroup,

	pub locations: Vec<Location>,
}

impl Ingredient {
	pub fn import(path: &str) -> Vec<Ingredient> {
		let mut ingredients: Vec<Ingredient> = vec![];

		// Loading multiple files into one vector due to the size of each board
		let paths = std::fs::read_dir(path)
			.unwrap()
			.filter_map(|f| f.ok())
			.map(|f| f.path())
			.filter_map(|p| match p.extension().is_some_and(|e| e == "toml") {
				true => Some(p),
				false => None,
			})
			.collect::<Vec<PathBuf>>();

		for path in paths {
			let str = std::fs::read_to_string(path).unwrap();
			let ingredient = toml::from_str::<Ingredient>(&str);
			if let Ok(ingredient) = ingredient {
				ingredients.push(ingredient);
			}
		}

		ingredients.sort_by(|a, b| a.group.cmp(&b.group));

		ingredients
	}
}

#[derive(Debug, Deserialize, PartialEq, Eq)]
pub struct Location {
	pub world: String,
	pub room: String,
	pub note: Option<String>,
}
