<?php

declare(strict_types=1);

use App\Framework\Deployment\Ssl\ValueObjects\CertificateStatus;

describe('CertificateStatus', function () {
    it('creates not found status', function () {
        $status = CertificateStatus::notFound();

        expect($status->exists)->toBeFalse();
        expect($status->isValid)->toBeFalse();
        expect($status->errors)->toContain('Certificate files not found');
    });

    it('creates status from certificate data', function () {
        $notBefore = new DateTimeImmutable('2024-01-01');
        $notAfter = new DateTimeImmutable('2024-12-31');

        $status = CertificateStatus::fromCertificateData(
            $notBefore,
            $notAfter,
            'Let\'s Encrypt Authority X3',
            'example.com'
        );

        expect($status->exists)->toBeTrue();
        expect($status->issuer)->toBe('Let\'s Encrypt Authority X3');
        expect($status->subject)->toBe('example.com');
    });

    it('detects expired certificate', function () {
        $notBefore = new DateTimeImmutable('-2 months');
        $notAfter = new DateTimeImmutable('-1 day');

        $status = CertificateStatus::fromCertificateData(
            $notBefore,
            $notAfter,
            'Test Issuer',
            'example.com'
        );

        expect($status->isExpired)->toBeTrue();
        expect($status->isValid)->toBeFalse();
    });

    it('detects expiring certificate', function () {
        $notBefore = new DateTimeImmutable('-2 months');
        $notAfter = new DateTimeImmutable('+15 days');

        $status = CertificateStatus::fromCertificateData(
            $notBefore,
            $notAfter,
            'Test Issuer',
            'example.com'
        );

        expect($status->isExpiring)->toBeTrue();
        expect($status->isExpired)->toBeFalse();
    });

    it('detects valid certificate', function () {
        $notBefore = new DateTimeImmutable('-1 month');
        $notAfter = new DateTimeImmutable('+60 days');

        $status = CertificateStatus::fromCertificateData(
            $notBefore,
            $notAfter,
            'Test Issuer',
            'example.com'
        );

        expect($status->isValid)->toBeTrue();
        expect($status->isExpiring)->toBeFalse();
        expect($status->isExpired)->toBeFalse();
    });

    it('determines renewal needed for expired certificate', function () {
        $notBefore = new DateTimeImmutable('-2 months');
        $notAfter = new DateTimeImmutable('-1 day');

        $status = CertificateStatus::fromCertificateData(
            $notBefore,
            $notAfter,
            'Test Issuer',
            'example.com'
        );

        expect($status->needsRenewal())->toBeTrue();
    });

    it('determines renewal needed for expiring certificate', function () {
        $notBefore = new DateTimeImmutable('-1 month');
        $notAfter = new DateTimeImmutable('+20 days');

        $status = CertificateStatus::fromCertificateData(
            $notBefore,
            $notAfter,
            'Test Issuer',
            'example.com'
        );

        expect($status->needsRenewal())->toBeTrue();
    });

    it('determines renewal not needed for valid certificate', function () {
        $notBefore = new DateTimeImmutable('-1 month');
        $notAfter = new DateTimeImmutable('+60 days');

        $status = CertificateStatus::fromCertificateData(
            $notBefore,
            $notAfter,
            'Test Issuer',
            'example.com'
        );

        expect($status->needsRenewal())->toBeFalse();
    });

    it('returns correct health status for expired', function () {
        $status = new CertificateStatus(
            exists: true,
            isValid: false,
            notBefore: null,
            notAfter: null,
            issuer: null,
            subject: null,
            daysUntilExpiry: -10,
            isExpiring: false,
            isExpired: true
        );

        expect($status->getHealthStatus())->toBe('expired');
    });

    it('returns correct health status for expiring', function () {
        $status = new CertificateStatus(
            exists: true,
            isValid: true,
            notBefore: null,
            notAfter: null,
            issuer: null,
            subject: null,
            daysUntilExpiry: 20,
            isExpiring: true,
            isExpired: false
        );

        expect($status->getHealthStatus())->toBe('expiring');
    });

    it('returns correct health status for invalid', function () {
        $status = new CertificateStatus(
            exists: true,
            isValid: false,
            notBefore: null,
            notAfter: null,
            issuer: null,
            subject: null,
            daysUntilExpiry: null,
            isExpiring: false,
            isExpired: false
        );

        expect($status->getHealthStatus())->toBe('invalid');
    });

    it('returns correct health status for missing', function () {
        $status = CertificateStatus::notFound();

        expect($status->getHealthStatus())->toBe('missing');
    });

    it('returns correct health status for healthy', function () {
        $notBefore = new DateTimeImmutable('-1 month');
        $notAfter = new DateTimeImmutable('+60 days');

        $status = CertificateStatus::fromCertificateData(
            $notBefore,
            $notAfter,
            'Test Issuer',
            'example.com'
        );

        expect($status->getHealthStatus())->toBe('healthy');
    });

    it('converts to array', function () {
        $notBefore = new DateTimeImmutable('2024-01-01');
        $notAfter = new DateTimeImmutable('2024-12-31');

        $status = CertificateStatus::fromCertificateData(
            $notBefore,
            $notAfter,
            'Test Issuer',
            'example.com'
        );

        $array = $status->toArray();

        expect($array)->toHaveKey('exists');
        expect($array)->toHaveKey('is_valid');
        expect($array)->toHaveKey('not_before');
        expect($array)->toHaveKey('not_after');
        expect($array)->toHaveKey('issuer');
        expect($array)->toHaveKey('subject');
        expect($array)->toHaveKey('days_until_expiry');
        expect($array)->toHaveKey('health_status');
    });
});
