<?php

declare(strict_types=1);

namespace Dealerdirect\Agreements\Tests\Pdf\Templates;

use Dealerdirect\Agreements\Enums\Locale;
use Dealerdirect\Agreements\Pdf\Templates\CarSalesAgreement;
use Dealerdirect\Agreements\Tests\TestCase;
use Dealerdirect\Agreements\Tests\Traits\DataObjectFixtures;

/**
 * @covers \Dealerdirect\Agreements\Pdf\Templates\CarSalesAgreement
 * @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 CarSalesAgreementTest 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 CarSalesAgreement($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 CarSalesAgreement($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->createMock(\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 CarSalesAgreement(Locale::NL_NL, $salesAgreement, $translator);
        $template->render();

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

    public function test_render_should_use_default_upholstery_when_not_provided(): 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(vehicle: $this->fixtureVehicle(upholstery: 0));
        $template = new CarSalesAgreement(Locale::NL_NL, $salesAgreement, $translator);
        $html = $template->render();

        $this->assertStringContainsString('vehicle.upholstery.0', $html, 'Template should use default upholstery');
    }

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