<?php

namespace MintyPHP\Tests\Module\Audit\Service;

use MintyPHP\Module\Audit\Service\SystemAuditRowPresenter;
use PHPUnit\Framework\TestCase;

class SystemAuditRowPresenterTest extends TestCase
{
    private SystemAuditRowPresenter $presenter;

    protected function setUp(): void
    {
        $this->presenter = new SystemAuditRowPresenter();
    }

    public function testPresentNormalizesEnumsAndFillsDefaults(): void
    {
        $out = $this->presenter->present([
            'id' => 42,
            'outcome' => 'success',
            'channel' => 'web',
            'event_type' => 'user.login',
        ]);

        $this->assertSame(42, $out['id']);
        $this->assertSame('success', $out['outcome']);
        $this->assertSame('user.login', $out['event_type']);
        $this->assertNotSame('', $out['outcome_label'], 'outcome_label should be translated, not empty');
        $this->assertNotSame('', $out['outcome_badge'], 'outcome_badge variant should be set');
        $this->assertSame(strtoupper($out['channel_label']), $out['channel_label'], 'channel label is uppercased');
        $this->assertSame($out['channel'], $out['channel_label'], 'channel and channel_label stay in sync');
    }

    public function testPresentFallsBackToDefaultsForUnknownEnumValues(): void
    {
        $out = $this->presenter->present([
            'outcome' => 'not-a-valid-outcome',
            'channel' => 'not-a-valid-channel',
        ]);

        $this->assertSame('success', $out['outcome'], 'unknown outcome falls back to success');
        $this->assertNotSame('', $out['channel'], 'unknown channel falls back to web/default');
    }

    public function testActorLabelPrefersDisplayName(): void
    {
        $out = $this->presenter->present([
            'actor_user_display_name' => 'Alice Doe',
            'actor_user_email' => 'alice@example.com',
        ]);

        $this->assertSame('Alice Doe', $out['actor_user_label']);
        $this->assertSame('alice@example.com', $out['actor_user_email']);
    }

    public function testActorLabelFallsBackToEmail(): void
    {
        $out = $this->presenter->present([
            'actor_user_display_name' => '',
            'actor_user_email' => 'bob@example.com',
        ]);

        $this->assertSame('bob@example.com', $out['actor_user_label']);
    }

    public function testActorLabelFallsBackToDashWhenNothingAvailable(): void
    {
        $out = $this->presenter->present([]);
        $this->assertSame('-', $out['actor_user_label']);
    }

    public function testActorLabelTrimsWhitespace(): void
    {
        $out = $this->presenter->present([
            'actor_user_display_name' => "   \t  ",
            'actor_user_email' => '  carol@example.com  ',
        ]);

        $this->assertSame('carol@example.com', $out['actor_user_label']);
    }

    public function testMissingFieldsAreSafeDefaults(): void
    {
        $out = $this->presenter->present([]);

        $this->assertSame(0, $out['id']);
        $this->assertSame('', $out['event_type']);
        $this->assertSame('', $out['target_type']);
        $this->assertSame('', $out['target_uuid']);
        $this->assertSame('', $out['request_id']);
        $this->assertSame('', $out['error_code']);
        $this->assertSame(0, $out['actor_user_id']);
    }

    public function testPresentAllMapsIterableToList(): void
    {
        $rows = (function () {
            yield ['id' => 1, 'outcome' => 'success'];
            yield ['id' => 2, 'outcome' => 'failed'];
        })();

        $out = $this->presenter->presentAll($rows);

        $this->assertCount(2, $out);
        $this->assertSame(1, $out[0]['id']);
        $this->assertSame(2, $out[1]['id']);
        $this->assertSame('failed', $out[1]['outcome']);
    }

    public function testPresentAllWithEmptyIterableReturnsEmptyArray(): void
    {
        $this->assertSame([], $this->presenter->presentAll([]));
    }
}
