<?php

declare(strict_types=1);

namespace App\Framework\FeatureFlags;

use App\Framework\Core\ValueObjects\Timestamp;

/**
 * Represents a feature flag configuration
 */
final readonly class FeatureFlag
{
    /**
     * @param array<string, mixed> $conditions
     */
    public function __construct(
        public string $name,
        public FeatureFlagStatus $status,
        public ?string $description = null,
        public array $conditions = [],
        public ?Timestamp $enabledAt = null,
        public ?Timestamp $expiresAt = null
    ) {
    }

    public function isEnabled(): bool
    {
        // Check if flag is explicitly disabled
        if ($this->status->isDisabled()) {
            return false;
        }

        // Check expiration
        if ($this->expiresAt !== null && Timestamp::now()->toFloat() > $this->expiresAt->toFloat()) {
            return false;
        }

        // If unconditionally enabled
        if ($this->status->isEnabled()) {
            return true;
        }

        // For conditional flags, we'll need context to evaluate
        return false;
    }

    public function isEnabledForContext(FeatureFlagContext $context): bool
    {
        // Check basic enabled status first
        if (! $this->isEnabled() && ! $this->status->isConditional()) {
            return false;
        }

        // If unconditionally enabled (and not expired)
        if ($this->status->isEnabled()) {
            return true;
        }

        // Evaluate conditions for conditional flags
        if ($this->status->isConditional()) {
            return $this->evaluateConditions($context);
        }

        return false;
    }

    private function evaluateConditions(FeatureFlagContext $context): bool
    {
        foreach ($this->conditions as $key => $expectedValue) {
            // Handle percentage rollout (e.g., percentage: 50)
            if ($key === 'percentage' && is_numeric($expectedValue)) {
                $hash = crc32($this->name . ':' . (string) $context->getUserId());
                $userPercentage = abs($hash) % 100;
                if ($userPercentage >= $expectedValue) {
                    return false;
                }

                continue;
            }

            $contextValue = $context->getValue($key);

            if ($contextValue === null) {
                return false; // Required context missing
            }

            // Handle array conditions (e.g., user_ids: [1, 2, 3])
            if (is_array($expectedValue)) {
                if (! in_array($contextValue, $expectedValue)) {
                    return false;
                }

                continue;
            }

            // Exact match
            if ($contextValue !== $expectedValue) {
                return false;
            }
        }

        return true;
    }

    public function withStatus(FeatureFlagStatus $status): self
    {
        return new self(
            $this->name,
            $status,
            $this->description,
            $this->conditions,
            $this->enabledAt,
            $this->expiresAt
        );
    }

    public function withConditions(array $conditions): self
    {
        return new self(
            $this->name,
            $this->status,
            $this->description,
            $conditions,
            $this->enabledAt,
            $this->expiresAt
        );
    }

    public function withExpiration(Timestamp $expiresAt): self
    {
        return new self(
            $this->name,
            $this->status,
            $this->description,
            $this->conditions,
            $this->enabledAt,
            $expiresAt
        );
    }
}
