#![expect(clippy::expect_used, reason = "examples can panic")]
#![expect(clippy::print_stderr, reason = "examples can log to stderr")]

use chrono_tz::Tz;
use ocpi_tariffs::{cdr, json, price, warning, Version};

fn main() {
    const CDR_JSON: &str = include_str!("data/cdr_time_and_parking_time.json");

    // If you know the version of a CDR you can parse it into a `json::Document` and validate it
    // against the schema for that version.
    let doc = json::parse_object(CDR_JSON).expect("unable to parse CDR");
    let (cdr, warnings) = cdr::build(doc, Version::V211).into_parts();

    if !warnings.is_empty() {
        eprintln!("The CDR has `{}` schema warnings.", warnings.len_warnings());
    }

    let report = match cdr::price(&cdr, price::TariffSource::UseCdr, Tz::Europe__Amsterdam) {
        Ok(r) => r,
        Err(set) => {
            let (error, warnings) = set.into_parts();
            print_pricing_error(&error);
            print_pricing_warnings(&warnings);
            return;
        }
    };

    let (report, warnings) = report.into_parts();
    print_pricing_warnings(&warnings);

    // The various fields of the `price::Report` can be examined or converted to JSON.
    let price::Report {
        periods: _,
        tariff_used: _,
        tariff_reports: _,
        timezone: _,
        billed_energy: _,
        billed_idle_time: _,
        total_charging_time: _,
        billed_charging_time: _,
        total_cost: _,
        total_fixed_cost: _,
        total_time: _,
        total_charging_time_cost: _,
        total_energy: _,
        total_energy_cost: _,
        total_idle_time: _,
        total_idle_cost: _,
    } = report;
}

/// Print `price::Warning` that halted the example to `stderr`.
fn print_pricing_error(error: &warning::Error<price::Warning>) {
    eprintln!(
        "ERR: Unable to price CDR due to error at path `{}`: {}",
        error.element().path,
        error.warning()
    );
}

/// Print `price::Warning`s to `stderr`.
fn print_pricing_warnings(warnings: &warning::Set<price::Warning>) {
    if warnings.is_empty() {
        return;
    }

    eprintln!(
        "WARN: {} warnings from the pricing:\n {}",
        warnings.len_warnings(),
        warning::SetWriter::new(warnings)
    );
}
