<?php

use App\Support\Money;

/**
 * Euros in, cents out.
 *
 * The console asked the owner to type cents, so a €799 plan was entered as
 * "79900" and one slipped digit was a factor of ten on an invoice.
 */

it('converts what an operator actually types', function (string $typed, ?int $cents) {
    expect(Money::toCents($typed))->toBe($cents);
})->with([
    ['799', 79900],
    ['79,90', 7990],       // German keyboard
    ['79.90', 7990],       // copied from somewhere
    ['0', 0],
    ['0,05', 5],
    [' 149 ', 14900],
    ['79,9', 7990],        // one decimal is still a price
    ['', null],
    ['neunzehn', null],
    ['1.000', null],       // a thousand, or one euro? refuse rather than guess
    ['79,999', null],      // no fractions of a cent
    ['-5', null],
    // Parses fine, then overflows the unsigned column — a typo must come back
    // as a message beside the field, not as a database error on submit.
    ['999999999', null],
    ['42949672,96', null],
    ['42949672,95', 4294967295],
]);

it('does not lose a cent to binary floating point', function () {
    // (float) '79.90' * 100 is 7989.999… and casting truncates to 7989 — one
    // cent short, on exactly the prices people charge.
    foreach (['79,90', '19,90', '0,29', '1234,56'] as $typed) {
        expect(Money::toCents($typed))->toBe((int) round((float) str_replace(',', '.', $typed) * 100), $typed);
    }

    expect(Money::toCents('79,90'))->toBe(7990)
        ->and(Money::toCents('0,29'))->toBe(29);
});

it('round-trips through the form', function () {
    foreach ([0, 5, 7990, 79900, 958800] as $cents) {
        expect(Money::toCents(Money::fromCents($cents)))->toBe($cents);
    }
});
