use crate::{
    datafile::{datafile::DataFile, segment::Segment},
    targeting::{conditions::TargetingCondition, models::SegmentCPModel, TargetingData},
};

pub(crate) struct SegmentCondition {
    segment_id: u32,
}

impl SegmentCondition {
    pub fn from_json(model: SegmentCPModel) -> Option<Self> {
        return Some(Self {
            segment_id: model.segment_id,
        });
    }
}

impl TargetingCondition for SegmentCondition {
    fn check(&self, data: &TargetingData<impl DataFile>) -> Option<bool> {
        Some(data.datafile.segments().get(&self.segment_id)?.tree().map_or(true, |tree| tree.check(data)))
    }
}

#[cfg(test)]
mod tests {
    use crate::{
        data::CustomData, datafile::segment::Segment, storage::visitor::Visitor, targeting::TargetingDataBuilder,
        utils::test_utils::load_datafile,
    };

    use super::*;
    use rstest::rstest;

    #[rstest]
    #[case(237130, None, false)]
    #[case(237130, Some(CustomData::new_with_index(1, vec!["true".to_owned()])), false)]
    #[case(237130, Some(CustomData::new_with_index(0, vec!["true".to_owned()])), true)]
    #[case(237132, None, false)]
    #[case(237132, Some(CustomData::new_with_index(0, vec!["true".to_owned()])), false)]
    #[case(237132, Some(CustomData::new_with_index(1, vec!["true".to_owned()])), true)]
    #[case(237133, None, false)]
    fn test_check(#[case] segment_id: u32, #[case] data_to_add: Option<CustomData>, #[case] expected: bool) {
        let datafile = load_datafile("resources/conditions/mock_segment_condition.json");
        let visitor = Visitor::new();
        if let Some(data_to_add) = data_to_add {
            visitor.wdata().custom_data_map.put(data_to_add, true);
        }
        let tar_tree = datafile.segments().get(&segment_id).unwrap().tree().unwrap();
        let actual = tar_tree.check(&TargetingDataBuilder::new().build(&datafile, &visitor.rdata()));
        assert_eq!(expected, actual);
    }
}
