use crate::{
    datafile::datafile::DataFile,
    targeting::{TargetingData, conditions::TargetingCondition, models::TargetPersonalizationCPModel},
};

pub(crate) struct TargetPersonalizationCondition {
    personalization_id: u32,
}

impl TargetPersonalizationCondition {
    pub fn from_json(model: TargetPersonalizationCPModel) -> Option<Self> {
        return Some(Self {
            personalization_id: model.personalization_id,
        });
    }
}

impl TargetingCondition for TargetPersonalizationCondition {
    fn check(&self, data: &TargetingData<impl DataFile>) -> Option<bool> {
        return Some(data.visitor_data.personalizations.r().get(&self.personalization_id).is_some());
    }
}

#[cfg(test)]
mod tests {
    use crate::{
        data::{BaseData, personalization::Personalization},
        datafile::datafile_test_utils::MockDataFile,
        storage::visitor::Visitor,
        targeting::TargetingDataBuilder,
        utils::test_utils::assert_targeting,
    };

    use rstest::rstest;

    #[rstest]
    #[case(None, false)]
    #[case(Some(vec![]), false)]
    #[case(Some(vec![Personalization::new(1)]), false)]
    #[case(Some(vec![Personalization::new(1)]), false)]
    #[case(Some(vec![Personalization::new(2)]), true)]
    #[case(Some(vec![Personalization::new(2)]), true)]
    fn test_check(#[case] personalizations: Option<Vec<Personalization>>, #[case] expected: bool) {
        let datafile = MockDataFile::default();
        let visitor = Visitor::new();
        if let Some(personalizations) = personalizations {
            visitor.add_data(personalizations.into_iter().map(|p| BaseData::Personalization(p)), true);
        }
        assert_targeting(
            "resources/conditions/mock_segment_target_perso.json",
            &TargetingDataBuilder::new().build(&datafile, &visitor.rdata()),
            expected,
        );
    }
}
