<?php

namespace App\Tests\Service;

use App\Entity\Printer;
use App\Service\PrinterService;
use Doctrine\ORM\EntityManagerInterface;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Serializer\SerializerInterface;
use function PHPUnit\Framework\once;

class PrinterServiceTest extends TestCase
{
    private readonly EntityManagerInterface&MockObject $entityManager;
    private readonly SerializerInterface&MockObject $serializer;
    private readonly PrinterService $printerService;

    protected function setUp(): void
    {
        $this->entityManager = self::createMock(EntityManagerInterface::class);
        $this->serializer = self::createMock(SerializerInterface::class);
        $this->printerService = new PrinterService($this->entityManager, $this->serializer);
    }

    #[Test]
    public function removeShouldInvokeRemoveOnPrinterAndFlush()
    {
        $printer = new Printer();

        $this->entityManager->expects(self::once())->method('remove')->with($printer);
        $this->entityManager->expects(self::once())->method('flush');

        $this->printerService->deletePrinter($printer);
    }

    #[Test]
    public function validateJsonShouldReturnFalseOnInputIncompleteJson()
    {
        $invalidJson = '{
            "name": "Bambu A1"
        }';

        self::assertFalse($this->printerService->validateJson($invalidJson));
    }

    #[Test]
    public function validateJsonShouldReturnTrueOnInputCompleteJson()
    {
        $validJson = '{
            "name": "Bambu A1 Mini",
            "price": 10.50,
            "build_volume": "180x180x180",
            "max_speed": 1000
        }';

        self::assertTrue($this->printerService->validateJson($validJson));
    }

    #[Test]
    public function createPrinterShouldInvokePersistAndFlushOnCreatedPrinterObject(){
        $json = '{
            "name": "Bambu A1 Mini",
            "price": 10.50,
            "build_volume": "180x180x180",
            "max_speed": 1000
        }';

        $printer = new Printer();
        $printer
            ->setName('Bambu A1 Mini')
            ->setPrice(10.50)
            ->setBuildVolume('180x180x180')
            ->setMaxSpeed(1000);

        $this->serializer->expects(self::once())->method('deserialize')->with($json)->willReturn($printer);
        $this->entityManager->expects(self::once())->method('persist')->with($printer);
        $this->entityManager->expects(self::once())->method('flush');

        $this->printerService->createPrinter($json);
    }

    #[Test]
    public function editPrinterShouldUpdatePrinterWithJsonContent(){
        $json = '{
            "name": "Bambu A1 Mini"
        }';

        $printer = new Printer();
        $printer
            ->setName('Bambu A1')
            ->setPrice(10.50)
            ->setBuildVolume('180x180x180')
            ->setMaxSpeed(1000);


        $expectedPrinter = new Printer();
        $expectedPrinter
            ->setName('Bambu A1 Mini')
            ->setPrice(10.50)
            ->setBuildVolume('180x180x180')
            ->setMaxSpeed(1000);

        $this->entityManager->expects(self::once())->method('flush');

        self::assertEquals($expectedPrinter, $this->printerService->editPrinter($printer, $json));
    }
}