#![allow(
    clippy::indexing_slicing,
    reason = "unwraps are allowed anywhere in tests"
)]

use rust_decimal::Decimal;
use rust_decimal_macros::dec;
use std::assert_matches;

use super::Warning;
use crate::json::{self, FromJson as _};

#[test]
fn should_parse_string() {
    const JSON: &str = r#"{
        "number": "3.14159"
    }"#;

    let doc = json::parse(JSON.into()).unwrap();
    let number_field = doc.root().find_field("number").unwrap();
    let number_elem = number_field.element();

    let number = Decimal::from_json(number_elem).unwrap();
    let (number, warnings) = number.into_parts();
    let warnings = warnings.path_map();
    let warnings = &*warnings["$.number"];

    assert_matches!(*warnings, [Warning::ExcessivePrecision]);
    assert_eq!(number, dec!(3.14159));
}

#[test]
fn should_fail_to_parse_numeric_str_letters() {
    const JSON: &str = r#"{
        "number": "3.14A1"
    }"#;

    let doc = json::parse(JSON.into()).unwrap();
    let number_field = doc.root().find_field("number").unwrap();
    let number_elem = number_field.element();

    let err_set = Decimal::from_json(number_elem).unwrap_err();
    let (error, warnings) = err_set.into_parts();
    let (error, _element) = error.into_parts();
    assert_matches!(error, Warning::Decimal(_));

    let warnings = warnings.path_map();
    assert!(warnings.is_empty());
}

#[test]
fn should_fail_to_parse_numeric_str_with_escapes() {
    const JSON: &str = r#"{
        "number": "3.14\n159"
    }"#;

    let doc = json::parse(JSON.into()).unwrap();
    let number_field = doc.root().find_field("number").unwrap();
    let number_elem = number_field.element();

    let err_set = Decimal::from_json(number_elem).unwrap_err();
    let (error, warnings) = err_set.into_parts();
    let (error, _element) = error.into_parts();
    assert_matches!(error, Warning::ContainsEscapeCodes);

    let warnings = warnings.path_map();
    assert!(warnings.is_empty());
}
