<?php

declare(strict_types=1);

namespace App\Administration\Application\Query\GetSubjects;

use App\Administration\Application\Dto\PaginatedResult;
use App\Administration\Domain\Model\SchoolClass\SchoolId;
use App\Administration\Domain\Repository\SubjectRepository;
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 GetSubjectsHandler
{
    public function __construct(
        private SubjectRepository $subjectRepository,
    ) {
    }

    /**
     * @return PaginatedResult<SubjectDto>
     */
    public function __invoke(GetSubjectsQuery $query): PaginatedResult
    {
        $subjects = $this->subjectRepository->findActiveByTenantAndSchool(
            TenantId::fromString($query->tenantId),
            SchoolId::fromString($query->schoolId),
        );

        if ($query->search !== null && $query->search !== '') {
            $searchLower = mb_strtolower($query->search);
            $subjects = array_filter(
                $subjects,
                static fn ($subject) => str_contains(mb_strtolower((string) $subject->name), $searchLower)
                    || str_contains(mb_strtolower((string) $subject->code), $searchLower),
            );
            $subjects = array_values($subjects);
        }

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

        return new PaginatedResult(
            items: array_map(
                static fn ($subject) => SubjectDto::fromDomain(
                    $subject,
                    teacherCount: 0,
                    classCount: 0,
                ),
                $items,
            ),
            total: $total,
            page: $query->page,
            limit: $query->limit,
        );
    }
}
