<?php

declare(strict_types=1);

namespace Dealerdirect\Agreements\Tests\Pdf;

use Dealerdirect\Agreements\Exceptions\PdfGenerationException;
use Dealerdirect\Agreements\Pdf\Generator;
use Dealerdirect\Agreements\Tests\TestCase;
use Dealerdirect\Agreements\Tests\Traits\DataObjectFixtures;
use Dompdf\Dompdf;
use Dompdf\Options;

/**
 * @covers \Dealerdirect\Agreements\Pdf\Generator
 * @covers \Dealerdirect\Agreements\Pdf\Templates\AbstractTemplate
 * @covers \Dealerdirect\Agreements\Enums\Locale
 */
final class GeneratorTest extends TestCase
{
    use DataObjectFixtures;

    private Generator $generator;

    public function setUp(): void
    {
        parent::setUp();

        $domPdf = Generator::applyOptionsToPdf(new Dompdf(), $this->getResourcesPath());

        $dataObject = $this->getMockForDataObject(['foo' => 'bar']);

        $template = $this->getTemplateMock($dataObject);

        $this->generator = new Generator($domPdf, $template);
    }

    public function test_generate_should_return_pdf(): void
    {
        $pdf = $this->generator->generate();

        $this->assertIsString($pdf);
        $this->assertStringStartsWith('%PDF', $pdf);
    }

    public function test_from_template_should_return_new_instance(): void
    {
        $generator = Generator::fromTemplate($this->generator->getTemplate());

        $this->assertInstanceOf(Generator::class, $generator);
    }

    /**
     * @covers \Dealerdirect\Agreements\Exceptions\PdfGenerationException
     */
    public function test_generate_should_throw_exception_when_failed_to_generate_pdf(): void
    {
        $this->expectException(PdfGenerationException::class);

        /** @var Dompdf|\PHPUnit\Framework\MockObject\MockObject $domPdf */
        $domPdf = $this->createPartialMock(Dompdf::class, ['output', 'render', 'getFontMetrics', 'getOptions']);
        $domPdf->method('render')->willReturn(null);
        $domPdf->method('output')->willReturn(false);
        $domPdf->method('getFontMetrics')->willReturn($this->createStub(\Dompdf\FontMetrics::class));
        $domPdf->method('getOptions')->willReturn(new Options([
            'chroot' => $this->getResourcesPath(),
            'fontDir' => $this->getResourcesPath() . '/fonts',
            'fontCache' => $this->getResourcesPath() . '/fonts/cache',
        ]));

        $template = $this->getTemplateMock();

        $generator = new Generator($domPdf, $template);
        $generator->generate();
    }

    public function test_validate_dompdf_options_should_throw_exception_when_chroot_is_not_set(): void
    {
        $this->expectException(\InvalidArgumentException::class);

        /** @var Dompdf|\PHPUnit\Framework\MockObject\MockObject $domPdf */
        $domPdf = $this->createPartialMock(Dompdf::class, ['output', 'render', 'getFontMetrics', 'getOptions']);
        $domPdf->method('render')->willReturn(null);
        $domPdf->method('output')->willReturn(false);
        $domPdf->method('getFontMetrics')->willReturn($this->createStub(\Dompdf\FontMetrics::class));
        $domPdf->method('getOptions')->willReturn(new Options());

        $template = $this->getTemplateMock();

        new Generator($domPdf, $template);
    }
}
