<?php

declare(strict_types=1);

namespace Tests\Unit\Framework\FeatureFlags;

use App\Framework\FeatureFlags\FeatureFlag;
use App\Framework\FeatureFlags\FeatureFlagContext;
use App\Framework\FeatureFlags\FeatureFlagStatus;
use App\Framework\Core\ValueObjects\Timestamp;

describe('FeatureFlag', function () {
    it('creates enabled feature flag', function () {
        $flag = new FeatureFlag(
            name: 'test-feature',
            status: FeatureFlagStatus::ENABLED,
            description: 'Test feature'
        );

        expect($flag->isEnabled())->toBeTrue();
        expect($flag->name)->toBe('test-feature');
        expect($flag->description)->toBe('Test feature');
    });

    it('creates disabled feature flag', function () {
        $flag = new FeatureFlag(
            name: 'test-feature',
            status: FeatureFlagStatus::DISABLED
        );

        expect($flag->isEnabled())->toBeFalse();
    });

    it('checks expiration', function () {
        $pastTime = Timestamp::fromTimestamp(time() - 3600);

        $flag = new FeatureFlag(
            name: 'expired-feature',
            status: FeatureFlagStatus::ENABLED,
            expiresAt: $pastTime
        );

        expect($flag->isEnabled())->toBeFalse();
    });

    it('enables flag for matching context', function () {
        $flag = new FeatureFlag(
            name: 'user-feature',
            status: FeatureFlagStatus::CONDITIONAL,
            conditions: ['user_id' => [1, 2, 3]]
        );

        $context = (new FeatureFlagContext())->withUserId('2');

        expect($flag->isEnabledForContext($context))->toBeTrue();
    });

    it('disables flag for non-matching context', function () {
        $flag = new FeatureFlag(
            name: 'user-feature',
            status: FeatureFlagStatus::CONDITIONAL,
            conditions: ['user_id' => [1, 2, 3]]
        );

        $context = (new FeatureFlagContext())->withUserId('99');

        expect($flag->isEnabledForContext($context))->toBeFalse();
    });

    it('handles percentage rollout', function () {
        $flag = new FeatureFlag(
            name: 'rollout-feature',
            status: FeatureFlagStatus::CONDITIONAL,
            conditions: ['percentage' => 50]
        );

        // Test with multiple user IDs to verify distribution
        $enabledCount = 0;
        for ($userId = 1; $userId <= 100; $userId++) {
            $context = (new FeatureFlagContext())->withUserId((string) $userId);
            if ($flag->isEnabledForContext($context)) {
                $enabledCount++;
            }
        }

        // Should be approximately 50% (allow some variance)
        expect($enabledCount)->toBeGreaterThan(30);
        expect($enabledCount)->toBeLessThan(70);
    });

    it('creates immutable copy with new status', function () {
        $original = new FeatureFlag(
            name: 'test-feature',
            status: FeatureFlagStatus::DISABLED
        );

        $updated = $original->withStatus(FeatureFlagStatus::ENABLED);

        expect($original->status)->toBe(FeatureFlagStatus::DISABLED);
        expect($updated->status)->toBe(FeatureFlagStatus::ENABLED);
        expect($original)->not->toBe($updated);
    });

    it('creates immutable copy with new conditions', function () {
        $original = new FeatureFlag(
            name: 'test-feature',
            status: FeatureFlagStatus::CONDITIONAL
        );

        $updated = $original->withConditions(['user_id' => [1, 2]]);

        expect($original->conditions)->toBeEmpty();
        expect($updated->conditions)->toBe(['user_id' => [1, 2]]);
    });

    it('creates immutable copy with expiration', function () {
        $original = new FeatureFlag(
            name: 'test-feature',
            status: FeatureFlagStatus::ENABLED
        );

        $expiry = Timestamp::fromTimestamp(time() + 3600);
        $updated = $original->withExpiration($expiry);

        expect($original->expiresAt)->toBeNull();
        expect($updated->expiresAt)->toBe($expiry);
    });

    it('handles multiple conditions', function () {
        $flag = new FeatureFlag(
            name: 'multi-condition',
            status: FeatureFlagStatus::CONDITIONAL,
            conditions: [
                'environment' => 'production',
                'user_id' => [1, 2, 3]
            ]
        );

        $matchingContext = (new FeatureFlagContext())
            ->withEnvironment('production')
            ->withUserId('2');

        $nonMatchingContext = (new FeatureFlagContext())
            ->withEnvironment('development')
            ->withUserId('2');

        expect($flag->isEnabledForContext($matchingContext))->toBeTrue();
        expect($flag->isEnabledForContext($nonMatchingContext))->toBeFalse();
    });
});
