use assert_matches::assert_matches;

use crate::{
    cdr,
    json::FromJson as _,
    price::{self, v221, Warning},
    test::{self, assert_no_unexpected_fields, datetime_from_str},
    ObjectType,
};

#[test]
fn should_pass_parse_validation() {
    test::setup();
    let json = cdr_json("2022-01-13T16:00:00Z", "2022-01-13T19:12:00Z");
    let cdr::ParseReport {
        cdr,
        unexpected_fields,
    } = cdr::parse_with_version(&json, crate::Version::V221).unwrap();
    assert_no_unexpected_fields(ObjectType::Cdr, &unexpected_fields);

    let (_cdr, warnings) = v221::Cdr::from_json(cdr.as_element()).unwrap().into_parts();
    assert!(warnings.is_empty());
}

#[test]
fn should_fail_validation_start_end_range_doesnt_overlap_with_periods() {
    test::setup();

    let json = cdr_json("2022-02-13T16:00:00Z", "2022-02-13T19:12:00Z");
    let cdr::ParseReport {
        cdr,
        unexpected_fields,
    } = cdr::parse_with_version(&json, crate::Version::V221).unwrap();
    assert_no_unexpected_fields(ObjectType::Cdr, &unexpected_fields);

    let (_cdr, warnings) = v221::Cdr::from_json(cdr.as_element()).unwrap().into_parts();
    let [warning] = warnings
        .into_path_as_str_map()
        .remove("$")
        .unwrap()
        .try_into()
        .unwrap();
    let (cdr_range, period_range) = assert_matches!(warning, Warning::PeriodsOutsideStartEndDateTime { cdr_range, period_range } => (cdr_range, period_range));

    {
        assert_eq!(cdr_range.start, datetime_from_str("2022-02-13T16:00:00Z"));
        assert_eq!(cdr_range.end, datetime_from_str("2022-02-13T19:12:00Z"));
    }
    {
        let period_range = assert_matches!(period_range, price::PeriodRange::Many(range) => range);

        assert_eq!(
            period_range.start,
            datetime_from_str("2022-01-13T16:00:00Z")
        );
        assert_eq!(period_range.end, datetime_from_str("2022-01-13T18:30:00Z"));
    }
}

fn cdr_json(start_date_time: &str, end_date_time: &str) -> String {
    let value = serde_json::json!({
        "country_code": "NL",
        "party_id": "ENE",
        "start_date_time": start_date_time,
        "end_date_time": end_date_time,
        "currency": "EUR",
        "tariffs": [],
        "cdr_location": {
            "country": "NLD"
        },
        "charging_periods": [
            {
                "start_date_time": "2022-01-13T16:00:00Z",
                "dimensions": [
                    {
                        "type": "TIME",
                        "volume": 2.5
                    }
                ]
            },
            {
                "start_date_time": "2022-01-13T18:30:00Z",
                "dimensions": [
                    {
                        "type": "PARKING_TIME",
                        "volume": 0.7
                    }
                ]
            }
        ],
        "total_cost": {
            "excl_vat": 11.25,
            "incl_vat": 12.75
        },
        "total_time_cost": {
            "excl_vat": 7.5,
            "incl_vat": 8.25
        },
        "total_parking_time": 0.7,
        "total_parking_cost": {
            "excl_vat": 3.75,
            "incl_vat": 4.5
        },
        "total_time": 3.2,
        "total_energy": 0,
        "last_updated": "2022-01-13T00:00:00Z"
    });

    value.to_string()
}
