<?php

declare(strict_types=1);

namespace App\Support\Verification;

use App\Models\OperationRun;

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

        return [[
            'key' => 'provider.connection.check',
            'title' => 'Provider connection check',
            'status' => 'fail',
            'severity' => 'critical',
            'blocking' => true,
            'reason_code' => 'unknown_error',
            'message' => 'Run was queued but never started. A queue worker may not be running.',
            'evidence' => self::evidence($run, $context),
            'next_steps' => [],
        ]];
    }

    /**
     * @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 : [];

        $targetScopeIdentifier = self::targetScopeIdentifier($targetScope);
        if ($targetScopeIdentifier !== null) {
            $identity['target_scope'] = self::targetScopeIdentity($targetScope);
        } else {
            $entraTenantId = $targetScope['entra_tenant_id'] ?? null;
            if (is_string($entraTenantId) && trim($entraTenantId) !== '') {
                $identity['entra_tenant_id'] = trim($entraTenantId);
            }
        }

        return $identity;
    }

    /**
     * @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 : [];

        $targetScopeIdentifier = self::targetScopeIdentifier($targetScope);
        if ($targetScopeIdentifier !== null) {
            $evidence[] = [
                'kind' => 'target_scope_identifier',
                'value' => $targetScopeIdentifier,
            ];
        } else {
            $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;
    }

    /**
     * @param  array<string, mixed>  $targetScope
     */
    private static function targetScopeIdentifier(array $targetScope): ?string
    {
        $scopeIdentifier = $targetScope['scope_identifier'] ?? null;

        return is_string($scopeIdentifier) && trim($scopeIdentifier) !== ''
            ? trim($scopeIdentifier)
            : null;
    }

    /**
     * @param  array<string, mixed>  $targetScope
     * @return array<string, string>
     */
    private static function targetScopeIdentity(array $targetScope): array
    {
        $identity = [];

        foreach (['provider', 'scope_kind', 'scope_identifier', 'scope_display_name'] as $key) {
            $value = $targetScope[$key] ?? null;

            if (is_string($value) && trim($value) !== '') {
                $identity[$key] = trim($value);
            }
        }

        return $identity;
    }
}
