use std::time::{Duration, SystemTime};

use jam_std_common::{BlockDesc, Node, NodeError};
use jam_types::{slot_period_sec, JAM_COMMON_ERA};

/// Best block description lazily updated on each slot.
pub struct CachedBestBlock {
	desc: BlockDesc,
}

impl CachedBestBlock {
	pub fn new() -> Self {
		let desc = BlockDesc { header_hash: Default::default(), slot: 0 };
		Self { desc }
	}

	/// Returns the best block description potentially querying it from the node.
	pub async fn get(&mut self, node: &impl Node) -> Result<&BlockDesc, NodeError> {
		let jce = SystemTime::UNIX_EPOCH + Duration::from_secs(JAM_COMMON_ERA);
		let duration_since_jce = SystemTime::now().duration_since(jce).unwrap_or(Duration::ZERO);
		let current_slot = duration_since_jce.as_secs() / slot_period_sec();
		if u64::from(self.desc.slot) < current_slot {
			self.desc = node.best_block().await?;
		}
		Ok(&self.desc)
	}
}
