<?php

declare(strict_types=1);

namespace App\Support\Audit;

use App\Services\Intune\SecretClassificationService;

final class AuditContextSanitizer
{
    private const REDACTED = '[REDACTED]';

    /**
     * @var array<int, string>
     */
    private const DROPPED_FIELDS = [
        'evidence_jsonb',
        'raw_evidence',
        'snapshot_payload',
    ];

    private const MAX_ITEMS = 50;

    private const MAX_STRING_LENGTH = 500;

    public static function sanitize(mixed $value): mixed
    {
        if (is_array($value)) {
            $sanitized = [];
            $count = 0;

            foreach ($value as $key => $item) {
                $count++;

                if ($count > self::MAX_ITEMS) {
                    $sanitized['truncated'] = true;

                    break;
                }

                if (is_string($key) && in_array($key, self::DROPPED_FIELDS, true)) {
                    continue;
                }

                if (is_string($key) && self::classifier()->protectsField('audit', $key)) {
                    $sanitized[$key] = self::REDACTED;

                    continue;
                }

                $sanitized[$key] = self::sanitize($item);
            }

            return $sanitized;
        }

        if (is_string($value)) {
            return self::sanitizeString($value);
        }

        return $value;
    }

    private static function sanitizeString(string $value): string
    {
        $candidate = trim($value);

        if ($candidate === '') {
            return $value;
        }

        $sanitized = self::classifier()->sanitizeAuditString($value);

        if (mb_strlen($sanitized) <= self::MAX_STRING_LENGTH) {
            return $sanitized;
        }

        return mb_substr($sanitized, 0, self::MAX_STRING_LENGTH).' [truncated]';
    }

    private static function classifier(): SecretClassificationService
    {
        return app(SecretClassificationService::class);
    }
}
