<?php

declare(strict_types=1);

use App\Framework\Auth\PasswordStrength;
use App\Framework\Auth\PasswordValidationResult;

describe('PasswordValidationResult', function () {
    it('constructs with all parameters', function () {
        $result = new PasswordValidationResult(
            isValid: true,
            errors: [],
            warnings: ['Consider adding special characters'],
            strengthScore: 75,
            strength: PasswordStrength::STRONG
        );

        expect($result->isValid)->toBeTrue();
        expect($result->errors)->toBe([]);
        expect($result->warnings)->toBe(['Consider adding special characters']);
        expect($result->strengthScore)->toBe(75);
        expect($result->strength)->toBe(PasswordStrength::STRONG);
    });

    it('detects errors', function () {
        $result = new PasswordValidationResult(
            isValid: false,
            errors: ['Too short'],
            warnings: [],
            strengthScore: 20,
            strength: PasswordStrength::WEAK
        );

        expect($result->hasErrors())->toBeTrue();
    });

    it('detects no errors', function () {
        $result = new PasswordValidationResult(
            isValid: true,
            errors: [],
            warnings: [],
            strengthScore: 90,
            strength: PasswordStrength::VERY_STRONG
        );

        expect($result->hasErrors())->toBeFalse();
    });

    it('detects warnings', function () {
        $result = new PasswordValidationResult(
            isValid: true,
            errors: [],
            warnings: ['Add numbers'],
            strengthScore: 65,
            strength: PasswordStrength::MODERATE
        );

        expect($result->hasWarnings())->toBeTrue();
    });

    it('detects no warnings', function () {
        $result = new PasswordValidationResult(
            isValid: true,
            errors: [],
            warnings: [],
            strengthScore: 95,
            strength: PasswordStrength::VERY_STRONG
        );

        expect($result->hasWarnings())->toBeFalse();
    });

    it('combines errors and warnings', function () {
        $result = new PasswordValidationResult(
            isValid: false,
            errors: ['Too short', 'No uppercase'],
            warnings: ['Add symbols'],
            strengthScore: 30,
            strength: PasswordStrength::WEAK
        );

        $allIssues = $result->getAllIssues();
        expect($allIssues)->toHaveCount(3);
        expect($allIssues)->toContain('Too short');
        expect($allIssues)->toContain('No uppercase');
        expect($allIssues)->toContain('Add symbols');
    });

    it('checks minimum requirements', function () {
        $valid = new PasswordValidationResult(
            isValid: true,
            errors: [],
            warnings: [],
            strengthScore: 60,
            strength: PasswordStrength::MODERATE
        );

        expect($valid->meetsMinimumRequirements())->toBeTrue();

        $invalid = new PasswordValidationResult(
            isValid: false,
            errors: ['Error'],
            warnings: [],
            strengthScore: 40,
            strength: PasswordStrength::WEAK
        );

        expect($invalid->meetsMinimumRequirements())->toBeFalse();

        $lowScore = new PasswordValidationResult(
            isValid: true,
            errors: [],
            warnings: [],
            strengthScore: 45,
            strength: PasswordStrength::WEAK
        );

        expect($lowScore->meetsMinimumRequirements())->toBeFalse();
    });

    it('checks if recommended', function () {
        $recommended = new PasswordValidationResult(
            isValid: true,
            errors: [],
            warnings: [],
            strengthScore: 85,
            strength: PasswordStrength::STRONG
        );

        expect($recommended->isRecommended())->toBeTrue();

        $withWarnings = new PasswordValidationResult(
            isValid: true,
            errors: [],
            warnings: ['Could be stronger'],
            strengthScore: 75,
            strength: PasswordStrength::STRONG
        );

        expect($withWarnings->isRecommended())->toBeFalse();

        $lowScore = new PasswordValidationResult(
            isValid: true,
            errors: [],
            warnings: [],
            strengthScore: 65,
            strength: PasswordStrength::MODERATE
        );

        expect($lowScore->isRecommended())->toBeFalse();
    });

    it('generates summary for invalid password', function () {
        $result = new PasswordValidationResult(
            isValid: false,
            errors: ['Too short', 'No numbers'],
            warnings: [],
            strengthScore: 20,
            strength: PasswordStrength::WEAK
        );

        $summary = $result->getSummary();
        expect($summary)->toContain('does not meet requirements');
        expect($summary)->toContain('Too short');
        expect($summary)->toContain('No numbers');
    });

    it('generates summary with warnings', function () {
        $result = new PasswordValidationResult(
            isValid: true,
            errors: [],
            warnings: ['Add symbols'],
            strengthScore: 65,
            strength: PasswordStrength::MODERATE
        );

        $summary = $result->getSummary();
        expect($summary)->toContain('Moderate');
        expect($summary)->toContain('suggestions');
        expect($summary)->toContain('Add symbols');
    });

    it('generates summary for valid password', function () {
        $result = new PasswordValidationResult(
            isValid: true,
            errors: [],
            warnings: [],
            strengthScore: 90,
            strength: PasswordStrength::VERY_STRONG
        );

        $summary = $result->getSummary();
        expect($summary)->toContain('Very Strong');
        expect($summary)->toContain('90/100');
    });

    it('converts to array', function () {
        $result = new PasswordValidationResult(
            isValid: true,
            errors: [],
            warnings: ['Warning message'],
            strengthScore: 75,
            strength: PasswordStrength::STRONG
        );

        $array = $result->toArray();

        expect($array)->toBeArray();
        expect($array['is_valid'])->toBeTrue();
        expect($array['errors'])->toBe([]);
        expect($array['warnings'])->toBe(['Warning message']);
        expect($array['strength_score'])->toBe(75);
        expect($array['strength'])->toBe('strong');
        expect($array['strength_label'])->toBe('Strong');
        expect($array['meets_minimum'])->toBeTrue();
        expect($array['is_recommended'])->toBeFalse(); // Has warnings
    });

    it('creates valid result', function () {
        $result = PasswordValidationResult::valid(95);

        expect($result->isValid)->toBeTrue();
        expect($result->errors)->toBe([]);
        expect($result->warnings)->toBe([]);
        expect($result->strengthScore)->toBe(95);
        expect($result->strength)->toBe(PasswordStrength::VERY_STRONG);
    });

    it('creates valid result with default score', function () {
        $result = PasswordValidationResult::valid();

        expect($result->strengthScore)->toBe(100);
        expect($result->strength)->toBe(PasswordStrength::VERY_STRONG);
    });

    it('creates invalid result', function () {
        $errors = ['Too short', 'No uppercase'];
        $result = PasswordValidationResult::invalid($errors, 25);

        expect($result->isValid)->toBeFalse();
        expect($result->errors)->toBe($errors);
        expect($result->warnings)->toBe([]);
        expect($result->strengthScore)->toBe(25);
        expect($result->strength)->toBe(PasswordStrength::WEAK);
    });

    it('creates invalid result with default score', function () {
        $result = PasswordValidationResult::invalid(['Error']);

        expect($result->strengthScore)->toBe(0);
    });
});
