<?php

namespace Apexl\Io\User\Entities;

use function Apexl\Config\config;
use Apexl\Io\Entity;
use Apexl\Io\Enums\Casts;
use Apexl\Io\Exceptions\RecordNotFoundException;
use Apexl\Io\Traits\HasCasts;
use DateTime;
use DateTimeImmutable;
use JsonSerializable;

/**
 * @property int $id
 * @property int $user_id
 * @property string $token
 * @property DateTimeImmutable $expiry
 * @property int|null $lifetime
 *
 */
class RefreshToken extends Entity implements JsonSerializable
{
    use HasCasts;

    public final const string TABLE = 'refresh_tokens';
    // Surrogate PK so a user can hold MANY refresh tokens (one per session /
    // device / app) instead of a single row that concurrent logins overwrite.
    public final const string PRIMARY_KEY = 'id';

    public static function newExpiryFrom(?int $now = null, ?int $lifetime = null): DateTimeImmutable
    {
        $expiry = new DateTime();
        // A row can carry its own lifetime (e.g. a "Stay signed in" / remember-me
        // login stored for 60 days). NULL falls back to the global config default.
        $lifetime ??= \Apexl\Config\config('auth.refresh.lifetime');
        $expiry->setTimestamp(($now ?? time()) + $lifetime);

        return DateTimeImmutable::createFromMutable($expiry);
    }

    public function casts(): array
    {
        return [
            'id' => Casts::INT,
            'user_id' => Casts::INT,
            'expiry' => Casts::DATETIME_STAMP,
            'lifetime' => Casts::INT,
        ];
    }

    public function isExpired(): bool
    {
        return $this->expiry && $this->expiry < new DateTimeImmutable();
    }

    /**
     * @throws RecordNotFoundException
     */
    public function user(): UserEntity
    {
        return UserEntity::fromPrimaryKey($this->user_id);
    }

    public function jsonSerialize(): string
    {
        return $this->data['token'];
    }
}
