use anchor_lang::prelude::*;
#[account(zero_copy)]
#[derive(AnchorDeserialize, Debug, PartialEq, Default)]
pub struct RolloverMetadata {
    pub index: u64,
    pub rollover_fee: u64,
    pub rollover_threshold: u64,
    pub network_fee: u64,
    pub rolledover_slot: u64,
    pub close_threshold: u64,
    pub additional_bytes: u64,
}
impl RolloverMetadata {
    pub fn new(
        index: u64,
        rollover_fee: u64,
        rollover_threshold: Option<u64>,
        network_fee: u64,
        close_threshold: Option<u64>,
        additional_bytes: Option<u64>,
    ) -> Self {
        Self {
            index,
            rollover_fee,
            rollover_threshold: rollover_threshold.unwrap_or(u64::MAX),
            network_fee,
            rolledover_slot: u64::MAX,
            close_threshold: close_threshold.unwrap_or(u64::MAX),
            additional_bytes: additional_bytes.unwrap_or_default(),
        }
    }
    pub fn rollover(&mut self) -> Result<()> {
        if self.rollover_threshold == u64::MAX {
            return err!(crate::errors::AccountCompressionErrorCode::RolloverNotConfigured);
        }
        if self.rolledover_slot != u64::MAX {
            return err!(crate::errors::AccountCompressionErrorCode::MerkleTreeAlreadyRolledOver);
        }
        #[cfg(target_os = "solana")]
        {
            self.rolledover_slot = Clock::get()?.slot;
        }
        Ok(())
    }
}
#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn test_rollover_metadata() {
        let mut metadata = RolloverMetadata::new(0, 0, Some(95), 0, Some(100), Some(1));
        assert_eq!(metadata.rollover_threshold, 95);
        assert_eq!(metadata.close_threshold, 100);
        assert_eq!(metadata.rolledover_slot, u64::MAX);
        assert_eq!(metadata.additional_bytes, 1);
        metadata.rollover().unwrap();
        let mut metadata = RolloverMetadata::new(0, 0, None, 0, None, None);
        assert_eq!(metadata.rollover_threshold, u64::MAX);
        assert_eq!(metadata.close_threshold, u64::MAX);
        assert_eq!(metadata.additional_bytes, 0);
        assert_eq!(
            metadata.rollover(),
            Err(crate::errors::AccountCompressionErrorCode::RolloverNotConfigured.into())
        );
        let mut metadata = RolloverMetadata::new(0, 0, Some(95), 0, None, None);
        assert_eq!(metadata.close_threshold, u64::MAX);
        metadata.rollover().unwrap();
        let mut metadata = RolloverMetadata::new(0, 0, Some(95), 0, None, None);
        metadata.rolledover_slot = 0;
        assert_eq!(metadata.close_threshold, u64::MAX);
        assert_eq!(
            metadata.rollover(),
            Err(crate::errors::AccountCompressionErrorCode::MerkleTreeAlreadyRolledOver.into())
        );
    }
}