<?php

declare(strict_types=1);

namespace App\Administration\Infrastructure\Persistence\InMemory;

use App\Administration\Domain\Model\HomeworkRules\EnforcementMode;
use App\Administration\Domain\Model\HomeworkRules\HomeworkRule;
use App\Administration\Domain\Model\User\UserId;
use App\Administration\Domain\Repository\HomeworkRulesHistoryRepository;
use App\Shared\Domain\Tenant\TenantId;

use function array_map;
use function array_slice;

use DateTimeImmutable;

use function json_encode;

use const JSON_THROW_ON_ERROR;

use Override;
use Ramsey\Uuid\Uuid;

final class InMemoryHomeworkRulesHistoryRepository implements HomeworkRulesHistoryRepository
{
    /** @var array<string, list<array{id: string, previous_rules: string|null, new_rules: string, enforcement_mode: string, enabled: bool, changed_by: string, changed_at: string}>> */
    private array $history = [];

    #[Override]
    public function record(
        TenantId $tenantId,
        ?array $previousRules,
        array $newRules,
        EnforcementMode $enforcementMode,
        bool $enabled,
        UserId $changedBy,
        DateTimeImmutable $changedAt,
    ): void {
        $key = (string) $tenantId;

        $previousJson = $previousRules !== null
            ? json_encode(
                array_map(static fn (HomeworkRule $r): array => $r->toArray(), $previousRules),
                JSON_THROW_ON_ERROR,
            )
            : null;

        $this->history[$key][] = [
            'id' => Uuid::uuid7()->toString(),
            'previous_rules' => $previousJson,
            'new_rules' => json_encode(
                array_map(static fn (HomeworkRule $r): array => $r->toArray(), $newRules),
                JSON_THROW_ON_ERROR,
            ),
            'enforcement_mode' => $enforcementMode->value,
            'enabled' => $enabled,
            'changed_by' => (string) $changedBy,
            'changed_at' => $changedAt->format(DateTimeImmutable::ATOM),
        ];
    }

    #[Override]
    public function findByTenant(TenantId $tenantId, int $limit = 50): array
    {
        $entries = $this->history[(string) $tenantId] ?? [];

        return array_slice(array_reverse($entries), 0, $limit);
    }
}
