<?php

declare(strict_types=1);

namespace App\Support\Verification;

use App\Models\OperationRun;
use App\Support\OpsUx\RunFailureSanitizer;
use App\Support\Providers\ProviderReasonCodes;

final class BlockedVerificationReportFactory
{
    /**
     * @return array<int, array<string, mixed>>
     */
    public static function checks(OperationRun $run): array
    {
        $context = is_array($run->context ?? null) ? $run->context : [];

        $reasonCode = self::normalizedReasonCode($context['reason_code'] ?? null);
        $message = self::blockedMessage($run);

        $nextSteps = $context['next_steps'] ?? [];
        $nextSteps = VerificationReportSanitizer::sanitizeNextStepsPayload($nextSteps);

        return [[
            'key' => 'provider.connection.check',
            'title' => 'Provider connection preflight',
            'status' => 'fail',
            'severity' => 'critical',
            'blocking' => true,
            'reason_code' => $reasonCode,
            'message' => $message,
            'evidence' => self::evidence($run, $context),
            'next_steps' => $nextSteps,
        ]];
    }

    /**
     * @return array<string, mixed>
     */
    public static function identity(OperationRun $run): array
    {
        $context = is_array($run->context ?? null) ? $run->context : [];

        $identity = [];

        $providerConnectionId = $context['provider_connection_id'] ?? null;
        if (is_numeric($providerConnectionId)) {
            $identity['provider_connection_id'] = (int) $providerConnectionId;
        }

        $targetScope = $context['target_scope'] ?? [];
        $targetScope = is_array($targetScope) ? $targetScope : [];

        $entraTenantId = $targetScope['entra_tenant_id'] ?? null;
        if (is_string($entraTenantId) && trim($entraTenantId) !== '') {
            $identity['entra_tenant_id'] = trim($entraTenantId);
        }

        return $identity;
    }

    private static function normalizedReasonCode(mixed $reasonCode): string
    {
        if (! is_string($reasonCode)) {
            return ProviderReasonCodes::UnknownError;
        }

        return RunFailureSanitizer::normalizeReasonCode($reasonCode);
    }

    private static function blockedMessage(OperationRun $run): string
    {
        $failures = is_array($run->failure_summary ?? null) ? $run->failure_summary : [];
        $firstFailure = $failures[0] ?? null;

        if (is_array($firstFailure) && is_string($firstFailure['message'] ?? null) && trim((string) $firstFailure['message']) !== '') {
            return trim((string) $firstFailure['message']);
        }

        return 'Operation blocked due to provider configuration.';
    }

    /**
     * @param  array<string, mixed>  $context
     * @return array<int, array{kind: string, value: int|string}>
     */
    private static function evidence(OperationRun $run, array $context): array
    {
        $evidence = [];

        $providerConnectionId = $context['provider_connection_id'] ?? null;
        if (is_numeric($providerConnectionId)) {
            $evidence[] = [
                'kind' => 'provider_connection_id',
                'value' => (int) $providerConnectionId,
            ];
        }

        $targetScope = $context['target_scope'] ?? [];
        $targetScope = is_array($targetScope) ? $targetScope : [];

        $entraTenantId = $targetScope['entra_tenant_id'] ?? null;
        if (is_string($entraTenantId) && trim($entraTenantId) !== '') {
            $evidence[] = [
                'kind' => 'entra_tenant_id',
                'value' => trim($entraTenantId),
            ];
        }

        $evidence[] = [
            'kind' => 'operation_run_id',
            'value' => (int) $run->getKey(),
        ];

        return $evidence;
    }
}
