<?php

declare(strict_types=1);

namespace App\Tests\Architecture;

use PHPat\Selector\Selector;
use PHPat\Test\Builder\BuildStep;
use PHPat\Test\PHPat;

/**
 * Tests ensuring Domain layer purity across all Bounded Contexts.
 *
 * The Domain layer must be pure PHP without framework dependencies.
 * This is critical for DDD architecture and testability.
 */
final class DomainPurityTest
{
    public function test_scolarite_domain_should_not_depend_on_infrastructure(): BuildStep
    {
        return PHPat::rule()
            ->classes(Selector::inNamespace('App\Scolarite\Domain'))
            ->shouldNotDependOn()
            ->classes(
                Selector::inNamespace('App\Scolarite\Infrastructure'),
                Selector::inNamespace('App\Shared\Infrastructure'),
                Selector::inNamespace('Symfony'),
                Selector::inNamespace('Doctrine'),
                Selector::inNamespace('ApiPlatform'),
            )
            ->because('Domain must be pure PHP without Infrastructure/framework dependencies');
    }

    public function test_vie_scolaire_domain_should_not_depend_on_infrastructure(): BuildStep
    {
        return PHPat::rule()
            ->classes(Selector::inNamespace('App\VieScolaire\Domain'))
            ->shouldNotDependOn()
            ->classes(
                Selector::inNamespace('App\VieScolaire\Infrastructure'),
                Selector::inNamespace('App\Shared\Infrastructure'),
                Selector::inNamespace('Symfony'),
                Selector::inNamespace('Doctrine'),
                Selector::inNamespace('ApiPlatform'),
            )
            ->because('Domain must be pure PHP without Infrastructure/framework dependencies');
    }

    public function test_communication_domain_should_not_depend_on_infrastructure(): BuildStep
    {
        return PHPat::rule()
            ->classes(Selector::inNamespace('App\Communication\Domain'))
            ->shouldNotDependOn()
            ->classes(
                Selector::inNamespace('App\Communication\Infrastructure'),
                Selector::inNamespace('App\Shared\Infrastructure'),
                Selector::inNamespace('Symfony'),
                Selector::inNamespace('Doctrine'),
                Selector::inNamespace('ApiPlatform'),
            )
            ->because('Domain must be pure PHP without Infrastructure/framework dependencies');
    }

    public function test_administration_domain_should_not_depend_on_infrastructure(): BuildStep
    {
        return PHPat::rule()
            ->classes(Selector::inNamespace('App\Administration\Domain'))
            ->shouldNotDependOn()
            ->classes(
                Selector::inNamespace('App\Administration\Infrastructure'),
                Selector::inNamespace('App\Shared\Infrastructure'),
                Selector::inNamespace('Symfony'),
                Selector::inNamespace('Doctrine'),
                Selector::inNamespace('ApiPlatform'),
            )
            ->because('Domain must be pure PHP without Infrastructure/framework dependencies');
    }

    public function test_scolarite_domain_should_not_depend_on_application(): BuildStep
    {
        return PHPat::rule()
            ->classes(Selector::inNamespace('App\Scolarite\Domain'))
            ->shouldNotDependOn()
            ->classes(Selector::inNamespace('App\Scolarite\Application'))
            ->because('Domain must not know about Application layer');
    }

    public function test_vie_scolaire_domain_should_not_depend_on_application(): BuildStep
    {
        return PHPat::rule()
            ->classes(Selector::inNamespace('App\VieScolaire\Domain'))
            ->shouldNotDependOn()
            ->classes(Selector::inNamespace('App\VieScolaire\Application'))
            ->because('Domain must not know about Application layer');
    }

    public function test_communication_domain_should_not_depend_on_application(): BuildStep
    {
        return PHPat::rule()
            ->classes(Selector::inNamespace('App\Communication\Domain'))
            ->shouldNotDependOn()
            ->classes(Selector::inNamespace('App\Communication\Application'))
            ->because('Domain must not know about Application layer');
    }

    public function test_administration_domain_should_not_depend_on_application(): BuildStep
    {
        return PHPat::rule()
            ->classes(Selector::inNamespace('App\Administration\Domain'))
            ->shouldNotDependOn()
            ->classes(Selector::inNamespace('App\Administration\Application'))
            ->because('Domain must not know about Application layer');
    }

    public function test_shared_domain_should_be_pure(): BuildStep
    {
        return PHPat::rule()
            ->classes(Selector::inNamespace('App\Shared\Domain'))
            ->shouldNotDependOn()
            ->classes(
                Selector::inNamespace('Symfony'),
                Selector::inNamespace('Doctrine'),
                Selector::inNamespace('ApiPlatform'),
                Selector::inNamespace('App\Shared\Infrastructure'),
                Selector::inNamespace('App\Shared\Application'),
            )
            ->because('Shared Domain must be pure PHP');
    }
}
