<?php

require_once BASE_PATH . '/config/database.php';

class RememberToken
{
    public const COOKIE_NAME = 'pet_spa_remember';
    private PDO $db;

    public function __construct()
    {
        $this->db = (new Database())->connect();
    }

    public function issue(int $userId, int $days = 30): string
    {
        $raw = bin2hex(random_bytes(32));
        $expiresAt = (new DateTimeImmutable('+' . max(1, $days) . ' days'))->format('Y-m-d H:i:s');
        try {
            $this->db->prepare('DELETE FROM remember_tokens WHERE expires_at <= NOW()')->execute();
            $this->db->prepare('INSERT INTO remember_tokens (user_id, token_hash, expires_at) VALUES (:user_id, :token_hash, :expires_at)')
                ->execute(['user_id' => $userId, 'token_hash' => hash('sha256', $raw), 'expires_at' => $expiresAt]);
            $this->setCookie($raw, strtotime($expiresAt));
            return $raw;
        } catch (PDOException) {
            // The application remains usable until the additive migration is applied.
            return '';
        }
    }

    public function restoreFromCookie(): ?array
    {
        $raw = $_COOKIE[self::COOKIE_NAME] ?? '';
        if (!is_string($raw) || !preg_match('/^[a-f0-9]{64}$/', $raw)) {
            $this->clearCookie();
            return null;
        }
        try {
            $stmt = $this->db->prepare(
                'SELECT u.* FROM remember_tokens rt JOIN users u ON u.id = rt.user_id
                 WHERE rt.token_hash = :token_hash AND rt.expires_at > NOW() AND u.status = "active" LIMIT 1'
            );
            $stmt->execute(['token_hash' => hash('sha256', $raw)]);
            $user = $stmt->fetch();
            if (!$user) {
                $this->clearCookie();
                return null;
            }
            $this->db->prepare('UPDATE remember_tokens SET last_used_at = NOW() WHERE token_hash = :token_hash')
                ->execute(['token_hash' => hash('sha256', $raw)]);
            return $user;
        } catch (PDOException) {
            return null;
        }
    }

    public function revokeRawCookie(): void
    {
        $raw = $_COOKIE[self::COOKIE_NAME] ?? '';
        if (is_string($raw) && preg_match('/^[a-f0-9]{64}$/', $raw)) {
            try {
                $this->db->prepare('DELETE FROM remember_tokens WHERE token_hash = :token_hash')
                    ->execute(['token_hash' => hash('sha256', $raw)]);
            } catch (PDOException) {
            }
        }
        $this->clearCookie();
    }

    public function revokeAllForUser(int $userId): void
    {
        try {
            $this->db->prepare('DELETE FROM remember_tokens WHERE user_id = :user_id')->execute(['user_id' => $userId]);
        } catch (PDOException) {
        }
        $this->clearCookie();
    }

    private function setCookie(string $value, int $expires): void
    {
        setcookie(self::COOKIE_NAME, $value, [
            'expires' => $expires, 'path' => '/', 'secure' => !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off',
            'httponly' => true, 'samesite' => 'Lax'
        ]);
    }

    private function clearCookie(): void
    {
        unset($_COOKIE[self::COOKIE_NAME]);
        setcookie(self::COOKIE_NAME, '', ['expires' => time() - 3600, 'path' => '/', 'secure' => !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off', 'httponly' => true, 'samesite' => 'Lax']);
    }
}
