<?php

declare(strict_types=1);

namespace App\Support\OpsUx;

use InvalidArgumentException;

final class BulkRunContext
{
    /**
     * @param  array{entra_tenant_id?: mixed, directory_context_id?: mixed}  $targetScope
     * @param  array{kind: string, ids_hash?: string, query_hash?: string}  $selectionIdentity
     * @param  array<string, mixed>  $extra
     * @return array<string, mixed>
     */
    public static function build(
        string $operationType,
        array $targetScope,
        array $selectionIdentity,
        string $fingerprint,
        array $extra = [],
    ): array {
        $targetScope = self::normalizeTargetScope($targetScope);

        return array_merge($extra, [
            'operation' => [
                'type' => trim($operationType),
            ],
            'target_scope' => $targetScope,
            'selection' => $selectionIdentity,
            'idempotency' => [
                'fingerprint' => trim($fingerprint),
            ],
        ]);
    }

    /**
     * @param  array{entra_tenant_id?: mixed, directory_context_id?: mixed}  $targetScope
     * @return array{entra_tenant_id?: string, directory_context_id?: string}
     */
    public static function normalizeTargetScope(array $targetScope): array
    {
        $entraTenantId = $targetScope['entra_tenant_id'] ?? null;
        $directoryContextId = $targetScope['directory_context_id'] ?? null;

        $normalized = [];

        if (is_string($entraTenantId) && trim($entraTenantId) !== '') {
            $normalized['entra_tenant_id'] = trim($entraTenantId);
        }

        if (is_string($directoryContextId) && trim($directoryContextId) !== '') {
            $normalized['directory_context_id'] = trim($directoryContextId);
        }

        if (is_int($directoryContextId)) {
            $normalized['directory_context_id'] = (string) $directoryContextId;
        }

        if (! isset($normalized['entra_tenant_id']) && ! isset($normalized['directory_context_id'])) {
            throw new InvalidArgumentException('Target scope must include entra_tenant_id or directory_context_id.');
        }

        return $normalized;
    }
}
