<?php

declare(strict_types=1);

namespace Dealerdirect\Agreements\Tests\Pdf\Templates;

use Dealerdirect\Agreements\Enums\Locale;
use Dealerdirect\Agreements\Pdf\Templates\BicycleSalesAgreement;
use Dealerdirect\Agreements\Tests\TestCase;
use Dealerdirect\Agreements\Tests\Traits\DataObjectFixtures;
use Dealerdirect\Generic\Category\BatteryWattage;
use Dealerdirect\Generic\Category\BicycleType;
use Dealerdirect\Generic\Category\EnginePosition;
use DealerDirect\Generic\Category\VehicleType;

/**
 * @covers \Dealerdirect\Agreements\Pdf\Templates\BicycleSalesAgreement
 * @covers \Dealerdirect\Agreements\Pdf\Templates\MotorbikeSalesAgreement
 * @covers \Dealerdirect\Agreements\Pdf\Templates\SalesAgreement
 * @covers \Dealerdirect\Agreements\Pdf\Templates\AbstractTemplate
 *
 * @uses \Dealerdirect\Agreements\DataObjects\Agent
 * @uses \Dealerdirect\Agreements\DataObjects\Conditions
 * @uses \Dealerdirect\Agreements\DataObjects\Contact
 * @uses \Dealerdirect\Agreements\DataObjects\SalesAgreement
 * @uses \Dealerdirect\Agreements\DataObjects\Vehicle
 * @uses \Dealerdirect\Agreements\Utils\GeneralUtils
 */
final class BicycleSalesAgreementTest extends TestCase
{
    use DataObjectFixtures;

    /**
     * @dataProvider provideLocales
     */
    public function test_can_construct_with_all_locales(Locale $locale): void
    {
        $this->expectNotToPerformAssertions();

        /** @var \Dealerdirect\Agreements\Utils\Translator|\PHPUnit\Framework\MockObject\MockObject $translator */
        $translator = $this->createStub(\Dealerdirect\Agreements\Utils\Translator::class);
        $translator->method('get')->willReturn('translated string');

        new BicycleSalesAgreement($locale, $this->fixtureSalesAgreement(), $translator);
    }

    /**
     * @dataProvider provideLocales
     *
     * @uses \Dealerdirect\Agreements\Utils\GeneralUtils
     */
    public function test_render_returns_valid_html(Locale $locale): void
    {
        /** @var \Dealerdirect\Agreements\Utils\Translator|\PHPUnit\Framework\MockObject\MockObject $translator */
        $translator = $this->createStub(\Dealerdirect\Agreements\Utils\Translator::class);
        $translator->method('get')->willReturn('translated string');

        $template = new BicycleSalesAgreement($locale, $this->fixtureSalesAgreement(), $translator);

        $this->assertStringIsValidHtml($template->render(), 'Template should render valid HTML');
    }

    /**
     * @uses \Dealerdirect\Agreements\Utils\GeneralUtils
     */
    public function test_render_should_pick_different_translation_when_pickup_is_false(): void
    {
        $calledTranslations = [];

        /** @var \Dealerdirect\Agreements\Utils\Translator|\PHPUnit\Framework\MockObject\MockObject $translator */
        $translator = $this->createStub(\Dealerdirect\Agreements\Utils\Translator::class);
        $translator->expects($this->any())
            ->method('get')
            ->willReturnCallback(function (string $key, array $attributes = []) use (&$calledTranslations) {
                $calledTranslations[] = $key;

                return 'translated string';
            })
        ;

        $salesAgreement = $this->fixtureSalesAgreement(pickUp: false);
        $template = new BicycleSalesAgreement(Locale::NL_NL, $salesAgreement, $translator);
        $template->render();

        $this->assertContains('sales_agreement.agreements.delivery_deliver', $calledTranslations);
    }

    public function test_render_should_translate_more_values_when_value_is_set(): void
    {
        /** @var \Dealerdirect\Agreements\Utils\Translator|\PHPUnit\Framework\MockObject\MockObject $translator */
        $translator = $this->createStub(\Dealerdirect\Agreements\Utils\Translator::class);
        $translator->method('get')->willReturnArgument(0);

        $salesAgreement = $this->fixtureSalesAgreement(
            vehicleType: VehicleType::BICYCLE,
            vehicle: $this->fixtureVehicle(
                bicycleType: BicycleType::ELECTRIC_MENS_BIKE,
                enginePosition: EnginePosition::CENTER,
                batteryWattage: BatteryWattage::BETWEEN_1000_AND_1099,
            ),
        );
        $template = new BicycleSalesAgreement(Locale::NL_NL, $salesAgreement, $translator);
        $html = $template->render();

        $this->assertStringContainsString(
            "bicycle.bicycle_type.{$salesAgreement->vehicle->bicycleType}",
            $html,
            'Bicycle type should be translated'
        );
        $this->assertStringContainsString(
            "bicycle.engine_position.{$salesAgreement->vehicle->enginePosition}",
            $html,
            'Engine position should be translated'
        );
        $this->assertStringContainsString(
            "bicycle.battery_wattage.{$salesAgreement->vehicle->batteryWattage}",
            $html,
            'Battery wattage should be translated'
        );
    }

    /**
     * @return array<array<Locale>>
     */
    public static function provideLocales(): array
    {
        return array_map(
            fn (Locale $locale) => [$locale],
            Locale::cases(),
        );
    }
}
