<?php

declare(strict_types=1);

namespace App\Scolarite\Infrastructure\Persistence\InMemory;

use App\Administration\Domain\Model\SchoolClass\ClassId;
use App\Administration\Domain\Model\User\UserId;
use App\Scolarite\Domain\Exception\HomeworkNotFoundException;
use App\Scolarite\Domain\Model\Homework\Homework;
use App\Scolarite\Domain\Model\Homework\HomeworkId;
use App\Scolarite\Domain\Model\Homework\HomeworkStatus;
use App\Scolarite\Domain\Repository\HomeworkRepository;
use App\Shared\Domain\Tenant\TenantId;

use function array_filter;
use function array_values;

use Override;

final class InMemoryHomeworkRepository implements HomeworkRepository
{
    /** @var array<string, Homework> */
    private array $byId = [];

    #[Override]
    public function save(Homework $homework): void
    {
        $this->byId[(string) $homework->id] = $homework;
    }

    #[Override]
    public function get(HomeworkId $id, TenantId $tenantId): Homework
    {
        $homework = $this->findById($id, $tenantId);

        if ($homework === null) {
            throw HomeworkNotFoundException::withId($id);
        }

        return $homework;
    }

    #[Override]
    public function findById(HomeworkId $id, TenantId $tenantId): ?Homework
    {
        $homework = $this->byId[(string) $id] ?? null;

        if ($homework === null || !$homework->tenantId->equals($tenantId)) {
            return null;
        }

        return $homework;
    }

    #[Override]
    public function findByTeacher(UserId $teacherId, TenantId $tenantId): array
    {
        return array_values(array_filter(
            $this->byId,
            static fn (Homework $h): bool => $h->teacherId->equals($teacherId)
                && $h->tenantId->equals($tenantId)
                && $h->status !== HomeworkStatus::DELETED,
        ));
    }

    #[Override]
    public function findByClass(ClassId $classId, TenantId $tenantId): array
    {
        return array_values(array_filter(
            $this->byId,
            static fn (Homework $h): bool => $h->classId->equals($classId)
                && $h->tenantId->equals($tenantId)
                && $h->status !== HomeworkStatus::DELETED,
        ));
    }

    #[Override]
    public function delete(HomeworkId $id, TenantId $tenantId): void
    {
        $key = (string) $id;

        if (isset($this->byId[$key]) && $this->byId[$key]->tenantId->equals($tenantId)) {
            unset($this->byId[$key]);
        }
    }
}
