<?php

namespace MintyPHP\Tests\App\Module;

use MintyPHP\App\Module\ModuleEvents;
use PHPUnit\Framework\TestCase;

final class ModuleEventsTest extends TestCase
{
    public function testAllConstantsAreReturnedByAll(): void
    {
        $reflection = new \ReflectionClass(ModuleEvents::class);
        $constants = $reflection->getConstants();

        self::assertNotEmpty($constants, 'ModuleEvents should define at least one constant');
        self::assertSame(
            array_values($constants),
            ModuleEvents::all(),
            'ModuleEvents::all() must return exactly the values of all class constants'
        );
    }

    public function testConstantValuesMatchExpectedEventStrings(): void
    {
        self::assertSame('user.login', ModuleEvents::USER_LOGIN);
        self::assertSame('user.logout', ModuleEvents::USER_LOGOUT);
        self::assertSame('user.created', ModuleEvents::USER_CREATED);
        self::assertSame('user.deleted', ModuleEvents::USER_DELETED);
        self::assertSame('user.activated', ModuleEvents::USER_ACTIVATED);
        self::assertSame('user.deactivated', ModuleEvents::USER_DEACTIVATED);
        self::assertSame('user.assignment_changed', ModuleEvents::USER_ASSIGNMENT_CHANGED);
        self::assertSame('scheduler.job_failed', ModuleEvents::SCHEDULER_JOB_FAILED);
    }

    public function testAllReturnsUniqueValues(): void
    {
        $all = ModuleEvents::all();
        self::assertSame($all, array_unique($all), 'ModuleEvents::all() must not contain duplicates');
    }

    public function testClassIsNotInstantiable(): void
    {
        $reflection = new \ReflectionClass(ModuleEvents::class);
        self::assertFalse($reflection->isInstantiable(), 'ModuleEvents should not be instantiable');
    }

    public function testDispatchCallSitesUseConstants(): void
    {
        $root = dirname(__DIR__, 3);
        $files = [
            $root . '/core/Service/Auth/AuthService.php',
            $root . '/core/Service/User/UserAccountService.php',
            $root . '/core/Service/Scheduler/SchedulerRunService.php',
        ];

        foreach ($files as $file) {
            $content = file_get_contents($file);
            self::assertIsString($content, "Could not read {$file}");

            // Ensure no raw string dispatch calls remain (except in ternaries which use constants)
            preg_match_all('/->dispatch\(\s*[\'"]([^"\']+)[\'"]\s*,/', $content, $matches);
            self::assertSame(
                [],
                $matches[1],
                basename($file) . ' still uses raw string event names: ' . implode(', ', $matches[1])
            );
        }
    }
}
