use serde::Deserialize;

#[derive(Debug, Deserialize)]
#[cfg_attr(test, derive(Clone))]
pub(crate) struct SegmentModel {
    pub id: u32,
    #[serde(rename = "audienceTracking")]
    pub audience_tracking: Option<bool>,
    #[serde(rename = "conditionsData")]
    pub condition_data: ConditionDataModel,
}

#[derive(Debug, Deserialize)]
#[cfg_attr(test, derive(Clone))]
pub(crate) struct ConditionDataModel {
    #[serde(rename = "firstLevel")]
    pub conditions: Vec<ConditionListModel>,
    #[serde(rename = "firstLevelOrOperators")]
    pub or_operators: Vec<bool>,
}

#[derive(Debug, Deserialize)]
#[cfg_attr(test, derive(Clone))]
pub(crate) struct ConditionListModel {
    pub conditions: Vec<ConditionModel>,
    #[serde(rename = "orOperators")]
    pub or_operators: Vec<bool>,
}

#[derive(Debug, Deserialize)]
#[cfg_attr(test, derive(Clone))]
pub(crate) struct ConditionModel {
    #[serde(rename = "isInclude")]
    pub is_include: Option<bool>,
    #[serde(flatten)]
    pub params: ConditionParamsModel,
}

#[derive(Debug, Deserialize)]
#[cfg_attr(test, derive(Clone))]
#[serde(tag = "targetingType", rename_all = "SCREAMING_SNAKE_CASE")]
pub(crate) enum ConditionParamsModel {
    Browser(BrowserCPModel),
    Conversions(ConversionsCPModel),
    Cookie(CookieCPModel),
    CustomDatum(CustomDatumCPModel),
    DeviceType(DeviceTypeCPModel),
    Geolocation(GeolocationCPModel),
    HeatSlice(HeatSliceCPModel),
    NewVisitors(NewVisitorsCPModel),
    OperatingSystem(OperatingSystemCPModel),
    PageTitle(PageTitleCPModel),
    PageUrl(PageUrlCPModel),
    PageViews(PageViewsCPModel),
    PreviousPage(PreviousPageCPModel),
    SameDayVisits(SameDayVisitsCPModel),
    SdkLanguage(SdkLanguageCPModel),
    Segment(SegmentCPModel),
    ExclusiveExperiment(ExclusiveExperimentCPModel),
    TargetExperiment(TargetExperimentCPModel),
    TargetFeatureFlag(TargetFeatureFlagCPModel),
    TargetPersonalization(TargetPersonalizationCPModel),
    FirstVisit(FirstLastVisitCPModel),
    LastVisit(FirstLastVisitCPModel),
    VisitorCode(VisitorCodeCPModel),
    Visits(VisitsCPModel),
    ApplicationVersion(VersionCPModel),
    #[serde(untagged)]
    Unknown(UnknownCPModel),
}

#[derive(Debug, Deserialize)]
#[cfg_attr(test, derive(Clone))]
pub(crate) struct BrowserCPModel {
    pub browser: String,
    pub version: Option<String>,
    #[serde(rename = "versionMatchType")]
    pub version_match_type: Option<String>,
}

#[derive(Debug, Deserialize)]
#[cfg_attr(test, derive(Clone))]
pub(crate) struct VisitParams {
    #[serde(rename = "visitScope")]
    pub visit_scope: Option<String>,
    #[serde(rename = "visitCount")]
    pub visit_count: Option<u32>,
}

#[derive(Debug, Deserialize)]
#[cfg_attr(test, derive(Clone))]
pub(crate) struct ConversionsCPModel {
    #[serde(rename = "goalId")]
    pub goal_id: Option<u32>,
    #[serde(flatten)]
    pub visit_params: VisitParams,
}

#[derive(Debug, Deserialize)]
#[cfg_attr(test, derive(Clone))]
pub(crate) struct CookieCPModel {
    pub name: String,
    #[serde(rename = "nameMatchType")]
    pub name_match_type: String,
    pub value: String,
    #[serde(rename = "valueMatchType")]
    pub value_match_type: String,
}

#[derive(Debug, Deserialize)]
#[cfg_attr(test, derive(Clone))]
pub(crate) struct CustomDatumCPModel {
    #[serde(rename = "customDataIndex")]
    pub custom_data_index: String,
    pub value: Option<String>,
    #[serde(rename = "valueMatchType")]
    pub value_match_type: String,
    // pub range: Option<Vec<String>>,
}

#[derive(Debug, Deserialize)]
#[cfg_attr(test, derive(Clone))]
pub(crate) struct DeviceTypeCPModel {
    pub device: String,
}

#[derive(Debug, Deserialize)]
#[cfg_attr(test, derive(Clone))]
pub(crate) struct ExclusiveExperimentCPModel {
    #[serde(rename = "campaignType")]
    pub campaign_type: String,
    #[serde(flatten)]
    pub visit_params: VisitParams,
}

#[derive(Debug, Deserialize)]
#[cfg_attr(test, derive(Clone))]
pub(crate) struct GeolocationCPModel {
    pub country: String,
    pub region: Option<String>,
    pub city: Option<String>,
}

#[derive(Debug, Deserialize)]
#[cfg_attr(test, derive(Clone))]
pub(crate) struct HeatSliceCPModel {
    #[serde(rename = "goalId")]
    pub goal_id: u32,
    #[serde(rename = "keyMomentId")]
    pub key_moment_id: u32,
    #[serde(rename = "lowerBound")]
    pub lower_bound: f64,
    #[serde(rename = "upperBound")]
    pub upper_bound: f64,
}

#[derive(Debug, Deserialize)]
#[cfg_attr(test, derive(Clone))]
pub(crate) struct NewVisitorsCPModel {
    #[serde(rename = "visitorType")]
    pub visitor_type: String,
}

#[derive(Debug, Deserialize)]
#[cfg_attr(test, derive(Clone))]
pub(crate) struct OperatingSystemCPModel {
    pub os: String,
}

#[derive(Debug, Deserialize)]
#[cfg_attr(test, derive(Clone))]
pub(crate) struct PageTitleCPModel {
    pub title: String,
    #[serde(rename = "matchType")]
    pub match_type: String,
}

#[derive(Debug, Deserialize)]
#[cfg_attr(test, derive(Clone))]
pub(crate) struct PageUrlCPModel {
    pub url: String,
    #[serde(rename = "matchType")]
    pub match_type: String,
}

#[derive(Debug, Deserialize)]
#[cfg_attr(test, derive(Clone))]
pub(crate) struct PageViewsCPModel {
    #[serde(rename = "pageCount")]
    pub page_count: u32,
    #[serde(rename = "matchType")]
    pub match_type: String,
}

#[derive(Debug, Deserialize)]
#[cfg_attr(test, derive(Clone))]
pub(crate) struct PreviousPageCPModel {
    pub url: String,
    #[serde(rename = "matchType")]
    pub match_type: String,
}

#[derive(Debug, Deserialize)]
#[cfg_attr(test, derive(Clone))]
pub(crate) struct SameDayVisitsCPModel {
    #[serde(rename = "visitCount")]
    pub visit_count: u32,
    #[serde(rename = "matchType")]
    pub match_type: String,
}

#[derive(Debug, Deserialize)]
#[cfg_attr(test, derive(Clone))]
pub(crate) struct SdkLanguageCPModel {
    #[serde(rename = "sdkLanguage")]
    pub sdk_language: String,
    pub version: Option<String>,
    #[serde(rename = "versionMatchType")]
    pub version_match_type: String,
}

#[derive(Debug, Deserialize)]
#[cfg_attr(test, derive(Clone))]
pub(crate) struct SegmentCPModel {
    #[serde(rename = "segmentId")]
    pub segment_id: u32,
}

#[derive(Debug, Deserialize)]
#[cfg_attr(test, derive(Clone))]
pub(crate) struct TargetExperimentCPModel {
    #[serde(rename = "experimentId")]
    pub experiment_id: u32,
    #[serde(rename = "variationId")]
    pub variation_id: Option<u32>,
    #[serde(rename = "variationMatchType")]
    pub variation_match_type: String,
    #[serde(flatten)]
    pub visit_params: VisitParams,
}

#[derive(Debug, Deserialize)]
#[cfg_attr(test, derive(Clone))]
pub(crate) struct TargetFeatureFlagCPModel {
    #[serde(rename = "featureFlagId")]
    pub feature_flag_id: u32,
    #[serde(rename = "variationKey")]
    pub variation_key: Option<String>,
    #[serde(rename = "ruleId")]
    pub rule_id: Option<u32>,
    #[serde(flatten)]
    pub visit_params: VisitParams,
}

#[derive(Debug, Deserialize)]
#[cfg_attr(test, derive(Clone))]
pub(crate) struct TargetPersonalizationCPModel {
    #[serde(rename = "personalizationId")]
    pub personalization_id: u32,
    #[serde(flatten)]
    pub visit_params: VisitParams,
}

#[derive(Debug, Deserialize)]
#[cfg_attr(test, derive(Clone))]
pub(crate) struct FirstLastVisitCPModel {
    #[serde(rename = "countInMillis")]
    pub count_in_millis: u64,
    #[serde(rename = "matchType")]
    pub match_type: String,
}

#[derive(Debug, Deserialize)]
#[cfg_attr(test, derive(Clone))]
pub(crate) struct VisitorCodeCPModel {
    #[serde(rename = "visitorCode")]
    pub visitor_code: String,
    #[serde(rename = "matchType")]
    pub match_type: String,
}

#[derive(Debug, Deserialize)]
#[cfg_attr(test, derive(Clone))]
pub(crate) struct VisitsCPModel {
    #[serde(rename = "visitCount")]
    pub visit_count: u32,
    #[serde(rename = "matchType")]
    pub match_type: String,
}

#[derive(Debug, Deserialize)]
#[cfg_attr(test, derive(Clone))]
pub(crate) struct VersionCPModel {
    pub version: String,
    #[serde(rename = "versionMatchType")]
    pub version_match_type: String,
}

#[derive(Debug, Deserialize)]
#[cfg_attr(test, derive(Clone))]
pub(crate) struct UnknownCPModel {
    #[serde(rename = "targetingType")]
    pub targeting_type: Option<String>,
}
