<?php

declare(strict_types=1);

namespace PhpWA\Client;

use InvalidArgumentException;
use PhpWA\Protocol\Jid\Jid;

final class GroupMetadata
{
    /** @var string */ private $groupJid;
    /** @var list<string> */ private $participants;
    /** @var string */ private $addressingMode;
    /** @var array<string,string> */ private $phoneToLid;

    /** @param list<string> $participants @param array<string,string> $phoneToLid */
    public function __construct(string $groupJid, array $participants, string $addressingMode, array $phoneToLid = [])
    {
        $group = Jid::parse($groupJid);
        if (!$group instanceof Jid || !$group->isGroup() || $group->device() !== null
            || ($addressingMode !== 'pn' && $addressingMode !== 'lid')
            || $participants === [] || count($participants) > 5000) {
            throw new InvalidArgumentException('Group metadata header is invalid.');
        }
        $unique = [];
        foreach ($participants as $value) {
            $jid = is_string($value) ? Jid::parse($value) : null;
            if (!$jid instanceof Jid || (!$jid->isPhoneNumber() && !$jid->isLid()
                && !$jid->isHostedPhoneNumber() && !$jid->isHostedLid())) {
                throw new InvalidArgumentException('Group metadata contains an invalid participant.');
            }
            $unique[(string) new Jid($jid->user(), $jid->server(), null, $jid->domainType())] = true;
        }
        // Reuse the strict mapping validator rather than allowing a second,
        // subtly different trust boundary for group metadata.
        $validated = new DeviceDiscoveryResult([], $phoneToLid);
        $this->groupJid = (string) $group; $this->participants = array_keys($unique);
        $this->addressingMode = $addressingMode; $this->phoneToLid = $validated->phoneToLid();
    }

    public function groupJid(): string { return $this->groupJid; }
    /** @return list<string> */ public function participants(): array { return $this->participants; }
    public function addressingMode(): string { return $this->addressingMode; }
    /** @return array<string,string> */ public function phoneToLid(): array { return $this->phoneToLid; }
}
