<?php
declare(strict_types=1);

use Phinx\Db\Adapter\AdapterInterface;
use Phinx\Migration\AbstractMigration;

/**
 * Per-row refresh-token lifetime (for "Stay signed in" / remember-me).
 *
 * RefreshToken computes its expiry from a single config value
 * (`auth.refresh.lifetime`). To let a "Stay signed in" login live much longer
 * than a normal one WITHOUT changing the global default, the chosen lifetime
 * (seconds) is stored on the row itself. NULL = "use the config default" (a
 * normal, non-remembered login), so existing rows keep working unchanged.
 *
 * On refresh the row's `lifetime` is carried forward, so a remembered session
 * stays remembered for its full window across refreshes (and, when rotation is
 * enabled, the rotated token inherits it too).
 */
final class AddLifetimeToRefreshTokens extends AbstractMigration
{
    public function up(): void
    {
        if ($this->hasLifetimeColumn()) {
            return;
        }

        // Nullable: NULL means "fall back to config('auth.refresh.lifetime')".
        $this->table('refresh_tokens')
            ->addColumn('lifetime', AdapterInterface::PHINX_TYPE_INTEGER, [
                'null' => true,
                'default' => null,
                'signed' => false,
                'after' => 'expiry',
            ])
            ->update();
    }

    public function down(): void
    {
        if (!$this->hasLifetimeColumn()) {
            return;
        }

        $this->table('refresh_tokens')
            ->removeColumn('lifetime')
            ->update();
    }

    private function hasLifetimeColumn(): bool
    {
        return (int) $this->fetchRow(
            "SELECT COUNT(*) c FROM information_schema.COLUMNS
             WHERE TABLE_SCHEMA = DATABASE()
               AND TABLE_NAME = 'refresh_tokens'
               AND COLUMN_NAME = 'lifetime'"
        )['c'] === 1;
    }
}
