<?php

declare(strict_types=1);

namespace App\Service;

use App\Model\User;
use Swoole\Table;

class ScopeTableManager
{
    protected Table $table;

    public function __construct(protected ScopeBitmapService $bitmapService)
    {
        $this->initTable();
    }

    /**
     * 初始化 Swoole\Table
     */
    protected function initTable(): void
    {
        $this->table = new Table(1024);
        $this->table->column('role', Table::TYPE_STRING, 32);
        $this->table->column('scope', Table::TYPE_STRING, 4096);
        $this->table->column('version', Table::TYPE_INT, 8);
        $this->table->create();
    }

    public function getTable(): Table
    {
        return $this->table;
    }

    /**
     * 获取用户 scope 数据，未命中时懒加载
     *
     * @param int $user_id
     * @return array{role: string, scope: string, version: int}|null
     */
    public function getUserScope(int $user_id): ?array
    {
        $key = (string) $user_id;
        $row = $this->table->get($key);

        if ($row !== false) {
            return $row;
        }

        // Table 未命中，从数据库加载
        return $this->rebuildUserScope($user_id);
    }

    /**
     * 重建用户 scope 并写入 Table
     *
     * @param int $user_id
     * @return array{role: string, scope: string, version: int}|null
     */
    public function rebuildUserScope(int $user_id): ?array
    {
        $user = User::query()->with('role')->find($user_id);
        if (!$user || !$user->role) {
            return null;
        }

        $role_name = $user->role->name;

        // administrator 不需要 bitmap
        if ($role_name === 'administrator') {
            $bitmap = '';
        } elseif ($role_name === 'developer') {
            $bitmap = $this->bitmapService->buildForDeveloper($user_id);
        } else {
            $bitmap = $this->bitmapService->buildForUser($user_id);
        }

        $data = [
            'role' => $role_name,
            'scope' => $bitmap,
            'version' => time(),
        ];

        $this->table->set((string) $user_id, $data);
        return $data;
    }

    /**
     * 清除用户 scope（权限变更时先清再重建）
     *
     * @param int $user_id
     * @return void
     */
    public function invalidateUser(int $user_id): void
    {
        $this->table->del((string) $user_id);
    }
}
