<?php

namespace MintyPHP\Module\Audit\Service;

use MintyPHP\Module\Audit\Domain\SystemAuditChannel;
use MintyPHP\Module\Audit\Domain\SystemAuditOutcome;

/**
 * Converts raw system audit log rows (as returned by the repository)
 * into a canonical presentation-ready row shape. One source of truth
 * shared by the Grid.js data endpoint and the CSV export endpoint, so
 * enum label translation, actor resolution, and timestamp formatting
 * can never drift between the UI and the download.
 */
final class SystemAuditRowPresenter
{
    /**
     * @param array<string,mixed> $row
     * @return array{
     *     id: int,
     *     created_at: string,
     *     event_type: string,
     *     outcome: string,
     *     outcome_badge: string,
     *     outcome_label: string,
     *     channel: string,
     *     channel_label: string,
     *     actor_user_id: int,
     *     actor_user_uuid: string,
     *     actor_user_label: string,
     *     actor_user_email: string,
     *     target_type: string,
     *     target_uuid: string,
     *     request_id: string,
     *     error_code: string
     * }
     */
    public function present(array $row): array
    {
        $outcome = SystemAuditOutcome::normalizeOr((string) ($row['outcome'] ?? ''), SystemAuditOutcome::Success);
        $channel = SystemAuditChannel::normalizeOr((string) ($row['channel'] ?? ''), SystemAuditChannel::Web);

        return [
            'id' => (int) ($row['id'] ?? 0),
            'created_at' => (string) dt((string) ($row['created_at'] ?? '')),
            'event_type' => (string) ($row['event_type'] ?? ''),
            'outcome' => $outcome->value,
            'outcome_badge' => $outcome->badgeVariant(),
            'outcome_label' => (string) t($outcome->labelToken()),
            'channel' => strtoupper($channel->labelToken()),
            'channel_label' => strtoupper($channel->labelToken()),
            'actor_user_id' => (int) ($row['actor_user_id'] ?? 0),
            'actor_user_uuid' => (string) ($row['actor_user_uuid'] ?? ''),
            'actor_user_label' => $this->resolveActorLabel($row),
            'actor_user_email' => (string) ($row['actor_user_email'] ?? ''),
            'target_type' => (string) ($row['target_type'] ?? ''),
            'target_uuid' => (string) ($row['target_uuid'] ?? ''),
            'request_id' => (string) ($row['request_id'] ?? ''),
            'error_code' => (string) ($row['error_code'] ?? ''),
        ];
    }

    /**
     * @api Called from data and export endpoints
     * @param iterable<array<string,mixed>> $rows
     * @return list<array<string,mixed>>
     */
    public function presentAll(iterable $rows): array
    {
        $result = [];
        foreach ($rows as $row) {
            $result[] = $this->present($row);
        }
        return $result;
    }

    private function resolveActorLabel(array $row): string
    {
        $name = trim((string) ($row['actor_user_display_name'] ?? ''));
        if ($name !== '') {
            return $name;
        }
        $email = trim((string) ($row['actor_user_email'] ?? ''));
        return $email !== '' ? $email : '-';
    }
}
