<?php

declare(strict_types=1);

namespace App\Framework\FeatureFlags;

use App\Framework\Http\IpAddress;
use App\Framework\UserAgent\UserAgent;

/**
 * Context for evaluating feature flags
 */
final readonly class FeatureFlagContext
{
    /**
     * @param array<string, mixed> $data
     */
    public function __construct(
        private array $data = [],
        private ?string $userId = null,
        private ?string $environment = null,
        private ?UserAgent $userAgent = null,
        private ?IpAddress $ipAddress = null
    ) {
    }

    public function getValue(string $key): mixed
    {
        return match($key) {
            'user_id' => $this->userId,
            'environment' => $this->environment,
            'user_agent' => $this->userAgent?->value,
            'ip_address' => $this->ipAddress?->value,
            default => $this->data[$key] ?? null,
        };
    }

    public function getUserId(): ?string
    {
        return $this->userId;
    }

    public function getEnvironment(): ?string
    {
        return $this->environment;
    }

    public function getUserAgent(): ?UserAgent
    {
        return $this->userAgent;
    }

    public function getIpAddress(): ?IpAddress
    {
        return $this->ipAddress;
    }

    public function withUserId(string $userId): self
    {
        return new self(
            $this->data,
            $userId,
            $this->environment,
            $this->userAgent,
            $this->ipAddress
        );
    }

    public function withEnvironment(string $environment): self
    {
        return new self(
            $this->data,
            $this->userId,
            $environment,
            $this->userAgent,
            $this->ipAddress
        );
    }

    public function withUserAgent(UserAgent $userAgent): self
    {
        return new self(
            $this->data,
            $this->userId,
            $this->environment,
            $userAgent,
            $this->ipAddress
        );
    }

    public function withIpAddress(IpAddress $ipAddress): self
    {
        return new self(
            $this->data,
            $this->userId,
            $this->environment,
            $this->userAgent,
            $ipAddress
        );
    }

    public function withData(array $data): self
    {
        return new self(
            array_merge($this->data, $data),
            $this->userId,
            $this->environment,
            $this->userAgent,
            $this->ipAddress
        );
    }

    public function with(string $key, mixed $value): self
    {
        return $this->withData([$key => $value]);
    }
}
