<?php

declare(strict_types=1);

namespace Blax\WebRtc\Rooms;

/**
 * A BACKEND-DEFINED room: the app declares these (config / a model) so clients
 * can only ever join a room that exists here — arbitrary client-chosen room
 * names are rejected. Carries the room's transport {@see RoomMode} and its
 * membership {@see RoomType} (derived from the id prefix unless overridden).
 */
final class RoomDefinition
{
    /** @param array<string,mixed> $meta free-form (label, description, …) for the app/UI */
    public function __construct(
        public readonly string $id,
        public readonly RoomMode $mode = RoomMode::P2P,
        public readonly ?int $limit = null,
        public readonly ?RoomType $type = null,
        public readonly array $meta = [],
    ) {}

    public function roomType(): RoomType
    {
        return $this->type ?? RoomType::fromName($this->id);
    }

    /**
     * Build from a declarative array (the config shape):
     *   'lobby' => ['mode' => 'sfu', 'limit' => 50, 'type' => 'presence', 'label' => '…']
     *
     * @param  array<string,mixed>  $config
     */
    public static function fromConfig(string $id, array $config): self
    {
        $known = ['mode', 'limit', 'type'];
        $meta = array_diff_key($config, array_flip($known));

        return new self(
            id: $id,
            mode: RoomMode::fromString($config['mode'] ?? null),
            limit: isset($config['limit']) ? (int) $config['limit'] : null,
            type: isset($config['type']) ? RoomType::tryFrom((string) $config['type']) : null,
            meta: $meta,
        );
    }

    /** @return array<string,mixed> */
    public function toArray(): array
    {
        return [
            'id' => $this->id,
            'mode' => $this->mode->value,
            'limit' => $this->limit,
            'type' => $this->roomType()->value,
            'meta' => $this->meta,
        ];
    }
}
