<?php

declare(strict_types=1);

namespace App\Tests\Service;

use App\Enum\ModelCategory;
use App\Tests\AbstractApiTestCase;

/**
 * @internal
 */
class ReferenceAutoGeneratorTest extends AbstractApiTestCase
{
    public function testGenerateWithFormula(): void
    {
        $mt = $this->createModelType('Roulement', 'ROUL-001', ModelCategory::PIECE);
        $mt->setReferenceFormula('{serie}{diametre}{type}');
        $mt->setRequiredFieldsForReference(['serie', 'diametre', 'type']);

        $em = $this->getEntityManager();
        $em->flush();

        $cfSerie    = $this->createCustomField('serie', 'text', typePiece: $mt);
        $cfDiametre = $this->createCustomField('diametre', 'text', typePiece: $mt);
        $cfType     = $this->createCustomField('type', 'text', typePiece: $mt);

        $piece = $this->createPiece('Roulement Test', null, $mt);

        $this->createCustomFieldValue($cfSerie, '22', piece: $piece);
        $this->createCustomFieldValue($cfDiametre, '07', piece: $piece);
        $this->createCustomFieldValue($cfType, 'K', piece: $piece);

        $em->refresh($piece);

        $generator = self::getContainer()->get('App\Service\ReferenceAutoGenerator');
        $result    = $generator->generate($piece);

        self::assertSame('2207K', $result);
    }

    public function testGenerateNormalizesValues(): void
    {
        $mt = $this->createModelType('Roulement Norm', 'ROUL-002', ModelCategory::PIECE);
        $mt->setReferenceFormula('{serie}{diametre}{type}');
        $mt->setRequiredFieldsForReference(['serie', 'diametre', 'type']);

        $em = $this->getEntityManager();
        $em->flush();

        $cfSerie    = $this->createCustomField('serie', 'text', typePiece: $mt);
        $cfDiametre = $this->createCustomField('diametre', 'text', typePiece: $mt);
        $cfType     = $this->createCustomField('type', 'text', typePiece: $mt);

        $piece = $this->createPiece('Roulement Norm', null, $mt);

        $this->createCustomFieldValue($cfSerie, ' 22 ', piece: $piece);
        $this->createCustomFieldValue($cfDiametre, '07', piece: $piece);
        $this->createCustomFieldValue($cfType, 'k', piece: $piece);

        $em->refresh($piece);

        $generator = self::getContainer()->get('App\Service\ReferenceAutoGenerator');
        $result    = $generator->generate($piece);

        self::assertSame('2207K', $result);
    }

    public function testGenerateReturnsNullWithoutFormula(): void
    {
        $mt    = $this->createModelType('Galet', 'GAL-001', ModelCategory::PIECE);
        $piece = $this->createPiece('Galet Test', null, $mt);

        $generator = self::getContainer()->get('App\Service\ReferenceAutoGenerator');
        $result    = $generator->generate($piece);

        self::assertNull($result);
    }

    public function testGenerateReturnsNullWhenNoModelType(): void
    {
        $piece = $this->createPiece('Orphan Piece');

        $generator = self::getContainer()->get('App\Service\ReferenceAutoGenerator');
        $result    = $generator->generate($piece);

        self::assertNull($result);
    }

    public function testGenerateReturnsNullWhenRequiredFieldsMissing(): void
    {
        $mt = $this->createModelType('Palier', 'PAL-001', ModelCategory::PIECE);
        $mt->setReferenceFormula('SNU {taille}');
        $mt->setRequiredFieldsForReference(['taille']);

        $em = $this->getEntityManager();
        $em->flush();

        $piece = $this->createPiece('Palier Test', null, $mt);

        $generator = self::getContainer()->get('App\Service\ReferenceAutoGenerator');
        $result    = $generator->generate($piece);

        self::assertNull($result);
    }

    public function testGenerateReturnsNullWhenRequiredFieldEmpty(): void
    {
        $mt = $this->createModelType('Palier Vide', 'PAL-003', ModelCategory::PIECE);
        $mt->setReferenceFormula('SNU {taille}');
        $mt->setRequiredFieldsForReference(['taille']);

        $em = $this->getEntityManager();
        $em->flush();

        $cfTaille = $this->createCustomField('taille', 'text', typePiece: $mt);
        $piece    = $this->createPiece('Palier Vide', null, $mt);
        $this->createCustomFieldValue($cfTaille, '   ', piece: $piece);

        $em->refresh($piece);

        $generator = self::getContainer()->get('App\Service\ReferenceAutoGenerator');
        $result    = $generator->generate($piece);

        self::assertNull($result);
    }

    public function testGenerateWithStaticTextInFormula(): void
    {
        $mt = $this->createModelType('Joint', 'JOINT-001', ModelCategory::PIECE);
        $mt->setReferenceFormula('U{taille}');

        $em = $this->getEntityManager();
        $em->flush();

        $cfTaille = $this->createCustomField('taille', 'text', typePiece: $mt);
        $piece    = $this->createPiece('Joint Test', null, $mt);
        $this->createCustomFieldValue($cfTaille, '507', piece: $piece);

        $em->refresh($piece);

        $generator = self::getContainer()->get('App\Service\ReferenceAutoGenerator');
        $result    = $generator->generate($piece);

        self::assertSame('U507', $result);
    }

    public function testGenerateWithAccentedFieldName(): void
    {
        $mt = $this->createModelType('Palier', 'PAL-ACCENT', ModelCategory::PIECE);
        $mt->setReferenceFormula('PA-{Diamètre}-33');
        $mt->setRequiredFieldsForReference(['Diamètre']);

        $em = $this->getEntityManager();
        $em->flush();

        $cf    = $this->createCustomField('Diamètre', 'number', typePiece: $mt);
        $piece = $this->createPiece('Palier 70', null, $mt);
        $this->createCustomFieldValue($cf, '70', piece: $piece);

        $em->refresh($piece);

        $generator = self::getContainer()->get('App\Service\ReferenceAutoGenerator');
        $result    = $generator->generate($piece);

        self::assertSame('PA-70-33', $result);
    }

    public function testGenerateWithNumberTypeField(): void
    {
        $mt = $this->createModelType('NumberField', 'NUM-001', ModelCategory::PIECE);
        $mt->setReferenceFormula('R-{taille}');
        $mt->setRequiredFieldsForReference(['taille']);

        $em = $this->getEntityManager();
        $em->flush();

        $cf    = $this->createCustomField('taille', 'number', typePiece: $mt);
        $piece = $this->createPiece('Piece Number', null, $mt);
        $this->createCustomFieldValue($cf, '42', piece: $piece);

        $em->refresh($piece);

        $generator = self::getContainer()->get('App\Service\ReferenceAutoGenerator');
        $result    = $generator->generate($piece);

        self::assertSame('R-42', $result);
    }

    public function testGenerateWithDecimalNumberField(): void
    {
        $mt = $this->createModelType('NumberDec', 'NUM-002', ModelCategory::PIECE);
        $mt->setReferenceFormula('R-{taille}');
        $mt->setRequiredFieldsForReference(['taille']);

        $em = $this->getEntityManager();
        $em->flush();

        $cf    = $this->createCustomField('taille', 'number', typePiece: $mt);
        $piece = $this->createPiece('Piece Dec', null, $mt);
        $this->createCustomFieldValue($cf, '12.5', piece: $piece);

        $em->refresh($piece);

        $generator = self::getContainer()->get('App\Service\ReferenceAutoGenerator');
        $result    = $generator->generate($piece);

        self::assertSame('R-12.5', $result);
    }

    public function testGenerateWithSpaceInFormula(): void
    {
        $mt = $this->createModelType('Palier2', 'PAL-002', ModelCategory::PIECE);
        $mt->setReferenceFormula('SNU {taille}');

        $em = $this->getEntityManager();
        $em->flush();

        $cfTaille = $this->createCustomField('taille', 'text', typePiece: $mt);
        $piece    = $this->createPiece('Palier Test 2', null, $mt);
        $this->createCustomFieldValue($cfTaille, '507', piece: $piece);

        $em->refresh($piece);

        $generator = self::getContainer()->get('App\Service\ReferenceAutoGenerator');
        $result    = $generator->generate($piece);

        self::assertSame('SNU 507', $result);
    }
}
