<?php

declare(strict_types=1);

namespace App\Administration\Application\Query\GetClasses;

use App\Administration\Application\Dto\PaginatedResult;
use App\Administration\Domain\Model\SchoolClass\AcademicYearId;
use App\Administration\Domain\Repository\ClassRepository;
use App\Shared\Domain\Tenant\TenantId;

use function array_slice;
use function count;

use Symfony\Component\Messenger\Attribute\AsMessageHandler;

#[AsMessageHandler(bus: 'query.bus')]
final readonly class GetClassesHandler
{
    public function __construct(
        private ClassRepository $classRepository,
    ) {
    }

    /**
     * @return PaginatedResult<ClassDto>
     */
    public function __invoke(GetClassesQuery $query): PaginatedResult
    {
        $classes = $this->classRepository->findActiveByTenantAndYear(
            TenantId::fromString($query->tenantId),
            AcademicYearId::fromString($query->academicYearId),
        );

        if ($query->search !== null && $query->search !== '') {
            $searchLower = mb_strtolower($query->search);
            $classes = array_filter(
                $classes,
                static fn ($class) => str_contains(mb_strtolower((string) $class->name), $searchLower)
                    || ($class->level !== null && str_contains(mb_strtolower($class->level->value), $searchLower)),
            );
            $classes = array_values($classes);
        }

        $total = count($classes);
        $offset = ($query->page - 1) * $query->limit;
        $items = array_slice($classes, $offset, $query->limit);

        return new PaginatedResult(
            items: array_map(
                static fn ($class) => ClassDto::fromDomain($class),
                $items,
            ),
            total: $total,
            page: $query->page,
            limit: $query->limit,
        );
    }
}
