//! Money helpers.
//!
//! Prices are stored throughout the app as integer **minor units** (cents).
//! This module is the single place that converts between that storage form and
//! the human-facing decimal strings shown in forms and templates.

use loco_rs::prelude::*;

/// Parse a price typed in major units ("12", "12.5", "12.34") into integer
/// minor units (cents). Rejects negatives and more than two decimals.
pub fn parse_price_to_cents(value: &str) -> Result<i64> {
    let value = value.trim().replace(',', ".");
    let invalid = || Error::BadRequest("invalid price".to_string());
    let (whole, frac) = match value.split_once('.') {
        Some((w, f)) => (w, f),
        None => (value.as_str(), ""),
    };
    if frac.len() > 2 || !whole.chars().all(|c| c.is_ascii_digit()) || whole.is_empty() {
        return Err(invalid());
    }
    if !frac.chars().all(|c| c.is_ascii_digit()) {
        return Err(invalid());
    }
    let whole: i64 = whole.parse().map_err(|_| invalid())?;
    let cents: i64 = match frac.len() {
        0 => 0,
        1 => frac.parse::<i64>().map_err(|_| invalid())? * 10,
        _ => frac.parse().map_err(|_| invalid())?,
    };
    Ok(whole * 100 + cents)
}

/// Render minor units as a human price string, e.g. `1234` -> `"12.34"`.
pub fn format_price(cents: i64) -> String {
    format!("{}.{:02}", cents / 100, (cents % 100).abs())
}
