<?php
namespace Tests\Unit\front\Controllers;

use PHPUnit\Framework\TestCase;
use front\Controllers\ShopBasketController;
use Domain\Order\OrderRepository;
use Domain\PaymentMethod\PaymentMethodRepository;

class ShopBasketControllerSummaryViewTest extends TestCase
{
    private $controller;

    protected function setUp(): void
    {
        $orderRepository = $this->createMock(OrderRepository::class);
        $paymentMethodRepository = $this->createMock(PaymentMethodRepository::class);
        $this->controller = new ShopBasketController($orderRepository, $paymentMethodRepository);
    }

    /**
     * Wywoluje chroniona metode calculateTransportCostForSummary przez Reflection.
     *
     * @param array|null $transport
     * @param float $productsSummary
     * @param float $freeDeliveryThreshold
     * @return array
     */
    private function invokeCalc($transport, $productsSummary, $freeDeliveryThreshold): array
    {
        $reflection = new \ReflectionClass(ShopBasketController::class);
        $method = $reflection->getMethod('calculateTransportCostForSummary');
        $method->setAccessible(true);

        return $method->invoke($this->controller, $transport, $productsSummary, $freeDeliveryThreshold);
    }

    public function testTransportWithDeliveryFreeBelowThresholdShowsRealCost(): void
    {
        // AC-1: delivery_free=1, basket 150, threshold 300 -> cost 15.00
        $transport = [
            'id'            => 4,
            'cost'          => 15.00,
            'delivery_free' => 1,
        ];

        $result = $this->invokeCalc($transport, 150.00, 300.00);

        $this->assertFalse($result['free_delivery_applies']);
        $this->assertSame(15.00, $result['transport_cost_effective']);
    }

    public function testTransportWithDeliveryFreeAboveThresholdShowsZero(): void
    {
        // AC-2: delivery_free=1, basket 350, threshold 300 -> cost 0.0, applies true
        $transport = [
            'id'            => 4,
            'cost'          => 15.00,
            'delivery_free' => 1,
        ];

        $result = $this->invokeCalc($transport, 350.00, 300.00);

        $this->assertTrue($result['free_delivery_applies']);
        $this->assertSame(0.0, $result['transport_cost_effective']);
    }

    public function testTransportWithDeliveryFreeAtExactThresholdShowsZero(): void
    {
        // Boundary: basket == threshold should trigger free delivery
        $transport = [
            'id'            => 4,
            'cost'          => 20.00,
            'delivery_free' => 1,
        ];

        $result = $this->invokeCalc($transport, 300.00, 300.00);

        $this->assertTrue($result['free_delivery_applies']);
        $this->assertSame(0.0, $result['transport_cost_effective']);
    }

    public function testTransportWithoutDeliveryFreeAlwaysShowsCost(): void
    {
        // AC-3: delivery_free=0, basket 500, threshold 300 -> cost 25.00, applies false
        $transport = [
            'id'            => 5,
            'cost'          => 25.00,
            'delivery_free' => 0,
        ];

        $result = $this->invokeCalc($transport, 500.00, 300.00);

        $this->assertFalse($result['free_delivery_applies']);
        $this->assertSame(25.00, $result['transport_cost_effective']);
    }

    public function testNullTransportReturnsZeroAndDoesNotApply(): void
    {
        // Scenario: no transport selected yet (findActiveByIdCached zwrocil null)
        $result = $this->invokeCalc(null, 500.00, 300.00);

        $this->assertFalse($result['free_delivery_applies']);
        $this->assertSame(0.0, $result['transport_cost_effective']);
    }

    public function testZeroFreeDeliveryThresholdDisablesFreeDelivery(): void
    {
        // Ochrona: jesli settings.free_delivery = 0, darmowa dostawa nie dziala nigdy
        $transport = [
            'id'            => 4,
            'cost'          => 15.00,
            'delivery_free' => 1,
        ];

        $result = $this->invokeCalc($transport, 9999.00, 0.00);

        $this->assertFalse($result['free_delivery_applies']);
        $this->assertSame(15.00, $result['transport_cost_effective']);
    }
}
