<?php

declare(strict_types=1);

namespace Tests\Framework\Health\ValueObjects;

use App\Framework\Health\ValueObjects\HealthMessage;
use App\Framework\Health\ValueObjects\HealthMessageType;
use InvalidArgumentException;

describe('HealthMessage Value Object', function () {
    it('can be created with message and type', function () {
        $message = new HealthMessage('Database connection successful', HealthMessageType::SUCCESS);

        expect($message->message)->toBe('Database connection successful');
        expect($message->type)->toBe(HealthMessageType::SUCCESS);
    });

    it('can be created with plain message', function () {
        $message = HealthMessage::plain('Simple message');

        expect($message->message)->toBe('Simple message');
        expect($message->type)->toBe(HealthMessageType::PLAIN);
    });

    it('can create success messages', function () {
        $message = HealthMessage::success('Database');

        expect($message->message)->toBe('Database is working correctly');
        expect($message->type)->toBe(HealthMessageType::SUCCESS);
        expect($message->isSuccess())->toBeTrue();
    });

    it('can create warning messages', function () {
        $message = HealthMessage::warning('Cache', 'High memory usage');

        expect($message->message)->toBe('Cache has issues: High memory usage');
        expect($message->type)->toBe(HealthMessageType::WARNING);
        expect($message->isWarning())->toBeTrue();
    });

    it('can create failure messages', function () {
        $message = HealthMessage::failure('API', 'Connection refused');

        expect($message->message)->toBe('API failed: Connection refused');
        expect($message->type)->toBe(HealthMessageType::FAILURE);
        expect($message->isError())->toBeTrue();
    });

    it('can create timeout messages', function () {
        $message = HealthMessage::timeout('Service', 5000.0);

        expect($message->message)->toBe('Service timed out after 5000ms');
        expect($message->type)->toBe(HealthMessageType::TIMEOUT);
        expect($message->isError())->toBeTrue();
    });

    it('can create degraded messages', function () {
        $message = HealthMessage::degraded('Queue', 'Processing slowly');

        expect($message->message)->toBe('Queue is degraded: Processing slowly');
        expect($message->type)->toBe(HealthMessageType::DEGRADED);
        expect($message->isWarning())->toBeTrue();
    });

    it('formats messages with emoji correctly', function () {
        $success = HealthMessage::success('Test');
        $warning = HealthMessage::warning('Test', 'Issue');
        $failure = HealthMessage::failure('Test', 'Error');

        expect($success->toFormattedString())->toBe('✓ Test is working correctly');
        expect($warning->toFormattedString())->toBe('⚠ Test has issues: Issue');
        expect($failure->toFormattedString())->toBe('✗ Test failed: Error');
    });

    it('can add prefix and suffix', function () {
        $message = HealthMessage::success('Database');

        $withPrefix = $message->withPrefix('MySQL');
        expect($withPrefix->message)->toBe('MySQL: Database is working correctly');
        expect($withPrefix->type)->toBe(HealthMessageType::SUCCESS);

        $withSuffix = $message->withSuffix('port 3306');
        expect($withSuffix->message)->toBe('Database is working correctly - port 3306');
    });

    it('can change type', function () {
        $message = HealthMessage::plain('Database status');
        $warningMessage = $message->withType(HealthMessageType::WARNING);

        expect($warningMessage->message)->toBe('Database status');
        expect($warningMessage->type)->toBe(HealthMessageType::WARNING);
        expect($warningMessage->isWarning())->toBeTrue();
    });

    it('converts to array correctly', function () {
        $message = HealthMessage::success('Test service');
        $array = $message->toArray();

        expect($array)->toHaveKey('message');
        expect($array)->toHaveKey('type');
        expect($array)->toHaveKey('formatted');
        expect($array)->toHaveKey('severity');
        expect($array)->toHaveKey('emoji');

        expect($array['message'])->toBe('Test service is working correctly');
        expect($array['type'])->toBe('success');
        expect($array['severity'])->toBe(0);
        expect($array['emoji'])->toBe('✓');
    });

    it('throws exception for empty message', function () {
        expect(fn () => new HealthMessage(''))->toThrow(InvalidArgumentException::class);
        expect(fn () => new HealthMessage('   '))->toThrow(InvalidArgumentException::class);
    });

    it('throws exception for too long message', function () {
        $longMessage = str_repeat('a', 501);
        expect(fn () => new HealthMessage($longMessage))->toThrow(InvalidArgumentException::class);
    });

    it('converts to string correctly', function () {
        $message = HealthMessage::success('Test');

        expect($message->toString())->toBe('Test is working correctly');
        expect((string) $message)->toBe('Test is working correctly');
    });
});
