<?php

declare(strict_types=1);

namespace Dealerdirect\Agreements\Tests\Pdf\Templates;

use Dealerdirect\Agreements\Enums\Locale;
use Dealerdirect\Agreements\Pdf\Templates\MotorbikeSalesAgreement;
use Dealerdirect\Agreements\Tests\TestCase;
use Dealerdirect\Agreements\Tests\Traits\DataObjectFixtures;
use DealerDirect\Generic\Category\Site;

/**
 * @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 MotorbikeSalesAgreementTest 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 MotorbikeSalesAgreement($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 MotorbikeSalesAgreement($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 MotorbikeSalesAgreement(Locale::NL_NL, $salesAgreement, $translator);
        $template->render();

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

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

        $salesAgreement = $this->fixtureSalesAgreement(siteReference: $reference);
        $template = new MotorbikeSalesAgreement(Locale::NL_NL, $salesAgreement, $translator);

        $html = $template->render();

        $this->assertStringContainsString(
            'labels.registration_possible',
            $html,
            'Should contain "registration_possible"'
        );
        $this->assertStringContainsString('labels.wok_notification', $html, 'Should contain "wok_notification"');
    }

    /**
     * @return array<string,int[]>
     */
    public static function provideScooterNLAndMotorNLReferences(): array
    {
        return [
            'Scooter NL' => [Site::REF_SCOOTER_NL],
            'Motor NL' => [Site::REF_MOTO_NL],
        ];
    }

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