<?php

declare(strict_types=1);

namespace App\Support;

use App\Support\AuditLogDisplay\DberpAuditLogFieldLabelResolver;

/**
 * 审计日志列表等界面：将动作码、快照键值格式化为中文可读文案。
 */
final class DberpAuditDisplay
{
    public static function actionLabel(?string $action): string
    {
        if ($action === null || $action === '') {
            return '—';
        }

        $map = __('dberp.options.audit_action');

        if (is_array($map) && isset($map[$action])) {
            return $map[$action];
        }

        if (preg_match('/^dberp\\.([a-z0-9_]+)\\.(created|updated|deleted)$/i', $action, $matches) === 1) {
            $resource = $matches[1];
            $verb = strtolower($matches[2]);
            $subject = self::resourceLabelFromAuditSegment($resource);

            return match ($verb) {
                'created' => sprintf('%s · %s', $subject, (string) __('dberp.audit.trail_created')),
                'updated' => sprintf('%s · %s', $subject, (string) __('dberp.audit.trail_updated')),
                'deleted' => sprintf('%s · %s', $subject, (string) __('dberp.audit.trail_deleted')),
                default => sprintf('%s · %s', $subject, $verb),
            };
        }

        return (string) __('dberp.audit.unknown_action');
    }

    public static function snapshotKeyLabel(string $key, ?string $auditableType = null): string
    {
        return app(DberpAuditLogFieldLabelResolver::class)->resolve($key, $auditableType);
    }

    public static function snapshotValueSummary(mixed $value): string
    {
        if ($value === null || $value === '') {
            return '—';
        }

        if (is_bool($value)) {
            return $value ? '是' : '否';
        }

        if (is_array($value)) {
            if ($value === []) {
                return '—';
            }

            $keys = array_keys($value);

            if ($keys === range(0, count($value) - 1)) {
                $parts = array_map(static fn (mixed $item): string => (string) $item, array_slice($value, 0, 6));

                $suffix = count($value) > 6 ? '…' : '';

                return implode('、', $parts).$suffix;
            }

            $pairs = [];
            $i = 0;

            foreach ($value as $nestedKey => $nestedValue) {
                if ($i >= 3) {
                    $pairs[] = '…';

                    break;
                }

                if (is_array($nestedValue)) {
                    $nestedValue = (string) __('dberp.audit.nested_value_omitted');
                }

                $pairs[] = self::snapshotKeyLabel((string) $nestedKey).'：'.self::snapshotValueSummary($nestedValue);
                $i++;
            }

            return implode('；', $pairs);
        }

        $string = (string) $value;

        if (mb_strlen($string) > 160) {
            return mb_substr($string, 0, 160).'…';
        }

        return $string;
    }

    public static function auditableSummary(?string $auditableType, mixed $auditableId): string
    {
        if (($auditableType === null || $auditableType === '') && ($auditableId === null || $auditableId === '')) {
            return '—';
        }

        $typeLabel = self::auditableTypeLabel($auditableType);
        $idPart = ($auditableId !== null && $auditableId !== '') ? ' #'.$auditableId : '';

        return $typeLabel.$idPart;
    }

    public static function auditableTypeLabel(?string $auditableType): string
    {
        if ($auditableType === null || $auditableType === '') {
            return (string) __('dberp.audit.auditable_type_none');
        }

        $short = class_basename($auditableType);
        $key = 'dberp.audit.entity.'.$short;
        $label = __($key);

        return $label !== $key ? $label : (string) __('dberp.audit_display.entity_type_unmapped');
    }

    private static function resourceLabelFromAuditSegment(string $segment): string
    {
        $segment = self::normalizeAuditResourceSegment($segment);
        $resourceKey = 'dberp.resources.'.$segment.'.label';
        $label = __($resourceKey);

        if ($label !== $resourceKey) {
            return $label;
        }

        $fallbackKey = 'dberp.audit.resource_fallback.'.$segment;
        $fallback = __($fallbackKey);

        return $fallback !== $fallbackKey ? $fallback : (string) __('dberp.audit_display.resource_unmapped');
    }

    /**
     * 审计动作里资源段命名与 Filament 资源键不完全一致时，映射到已有翻译键。
     */
    private static function normalizeAuditResourceSegment(string $segment): string
    {
        return match ($segment) {
            'number_rule' => 'number_sequence',
            default => $segment,
        };
    }
}
