<?php

declare(strict_types=1);

namespace App\Tests\Unit\Service\Export\Encoder;

use App\Service\Export\Encoder\DocXEncoder;
use App\Service\Utils\FileUtils;
use Phpdocx\Create\CreateDocx;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;

class DocXEncoderTest extends TestCase
{
    private MockObject|CreateDocx $phpDocx;
    private MockObject|FileUtils $fileUtils;

    public function setUp(): void
    {
        $this->phpDocx = $this->getMockBuilder(CreateDocx::class)->disableOriginalConstructor()->getMock();
        $this->fileUtils = $this->getMockBuilder(FileUtils::class)->disableOriginalConstructor()->getMock();
    }

    public function testSupport(): void
    {
        $encoder = $this->getMockBuilder(DocXEncoder::class)
            ->setConstructorArgs([$this->phpDocx, $this->fileUtils])
            ->setMethodsExcept(['support'])
            ->getMock();

        $this->assertTrue($encoder->support('docx'));
        $this->assertFalse($encoder->support('txt'));
    }

    public function testEncode(): void
    {
        $encoder = $this->getMockBuilder(DocXEncoder::class)
            ->setConstructorArgs([$this->phpDocx, $this->fileUtils])
            ->setMethodsExcept(['encode'])
            ->getMock();

        $this->fileUtils
            ->expects(self::once())
            ->method('getTempFilename')
            ->with('docx')
            ->willReturn('tmp/temp.docx');

        $this->phpDocx
            ->expects($this->once())
            ->method('embedHtml')
            ->with('<div>content</div>');

        $this->phpDocx
            ->expects(self::once())
            ->method('createDocx')
            ->with('tmp/temp.docx');

        $this->fileUtils
            ->expects(self::once())
            ->method('getFileContent')
            ->with('tmp/temp.docx')
            ->willReturn('%%encoded%%');

        $this->fileUtils
            ->expects(self::once())
            ->method('rmIfExist')
            ->with('tmp/temp.docx');

        $this->assertEquals(
            '%%encoded%%',
            $encoder->encode('<div>content</div>')
        );
    }

    public function testEncodeWithError(): void
    {
        $encoder = $this->getMockBuilder(DocXEncoder::class)
            ->setConstructorArgs([$this->phpDocx, $this->fileUtils])
            ->setMethodsExcept(['encode'])
            ->getMock();

        $this->fileUtils
            ->method('getTempFilename')
            ->with('docx')
            ->willReturn('tmp/temp.docx');

        $this->phpDocx
            ->method('embedHtml')
            ->with('<div>content</div>');

        $this->phpDocx
            ->method('createDocx')
            ->with('tmp/temp.docx');

        $this->fileUtils
            ->method('getFileContent')
            ->willThrowException(new \Exception('error'));

        $this->fileUtils
            ->expects(self::once())
            ->method('rmIfExist')
            ->with('tmp/temp.docx');

        $this->expectException(\Exception::class);
        $this->expectExceptionMessage('error');

        $encoder->encode('<div>content</div>');
    }
}
