<?php

declare(strict_types=1);

namespace Tests\Unit;

use App\ValueObjects\Money;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\TestCase;

/**
 * #94 — multiply/divide/percentage normalizan el factor escalar antes de BCMath.
 * Un float pequeño se castea a notación científica ("5.0E-7") que BCMath rechaza
 * (ValueError en PHP 8.3) o malinterpreta; normalize() lo convierte con sprintf.
 */
class MoneyScientificFactorTest extends TestCase
{
    #[Test]
    public function multiply_handles_scientific_notation_float_factor(): void
    {
        // 1_000_000 * 0.0000005 = 0.5 ; (string) 5.0E-7 = "5.0E-7"
        $this->assertSame('0.50', Money::of('1000000')->multiply(5.0E-7)->toString());
    }

    #[Test]
    public function divide_handles_scientific_notation_float_divisor(): void
    {
        // 1 / 0.0000005 = 2_000_000
        $this->assertSame('2000000.00', Money::of('1')->divide(5.0E-7)->toString());
    }

    #[Test]
    public function percentage_handles_scientific_notation_float(): void
    {
        // 1_000_000 * (0.00005 / 100) = 0.5
        $this->assertSame('0.50', Money::of('1000000')->percentage(5.0E-5)->toString());
    }

    #[Test]
    public function normal_factors_still_work(): void
    {
        $this->assertSame('500.00', Money::of('1000')->multiply(0.5)->toString());
        $this->assertSame('250.00', Money::of('1000')->divide(4)->toString());
        $this->assertSame('100.00', Money::of('1000')->percentage(10)->toString());
    }

    #[Test]
    public function cents_is_consistent_with_to_string(): void
    {
        // #97 — cents() deriva del valor truncado a precision, así que nunca
        // diverge de toString() (antes truncaba el monto interno de 8 decimales).
        foreach (['0.985', '12.34', '1000', '0.01', '99.999'] as $raw) {
            $money = Money::of($raw);
            $expected = (int) round(((float) $money->toString()) * 100);
            $this->assertSame($expected, $money->cents(), "cents() inconsistente para {$raw}");
        }
    }
}
