<?php

declare(strict_types=1);

namespace App\Support\References\Resolvers;

use App\Support\References\ReferenceClass;
use App\Support\References\ReferenceDescriptor;
use App\Support\References\ReferenceResolutionState;
use App\Support\References\ReferenceResolverRegistry;
use App\Support\References\ReferenceTechnicalDetail;
use App\Support\References\ResolvedReference;

final class AssignmentTargetReferenceResolver
{
    public function __construct(
        private readonly ReferenceResolverRegistry $registry,
    ) {}

    /**
     * @param  array<string, mixed>  $target
     * @param  array<string, mixed>  $context
     */
    public function resolve(array $target, array $context = []): ResolvedReference
    {
        $targetType = strtolower((string) ($context['target_type'] ?? ($target['@odata.type'] ?? '')));
        $targetId = (string) ($context['target_id'] ?? ($target['groupId'] ?? $target['collectionId'] ?? ''));

        if (str_contains($targetType, 'alldevicesassignmenttarget')) {
            return new ResolvedReference(
                referenceClass: ReferenceClass::TenantExternalObject,
                rawIdentifier: $targetId !== '' ? $targetId : 'all_devices',
                primaryLabel: 'All devices',
                secondaryLabel: 'Assignment target',
                state: ReferenceResolutionState::Resolved,
                stateLabel: null,
                linkTarget: null,
                technicalDetail: ReferenceTechnicalDetail::forIdentifier($targetId !== '' ? $targetId : 'all_devices', 'Captured from assignment evidence'),
            );
        }

        if (str_contains($targetType, 'allusersassignmenttarget') || str_contains($targetType, 'alllicensedusersassignmenttarget')) {
            return new ResolvedReference(
                referenceClass: ReferenceClass::TenantExternalObject,
                rawIdentifier: $targetId !== '' ? $targetId : 'all_users',
                primaryLabel: 'All users',
                secondaryLabel: 'Assignment target',
                state: ReferenceResolutionState::Resolved,
                stateLabel: null,
                linkTarget: null,
                technicalDetail: ReferenceTechnicalDetail::forIdentifier($targetId !== '' ? $targetId : 'all_users', 'Captured from assignment evidence'),
            );
        }

        if (str_contains($targetType, 'groupassignmenttarget')) {
            $groupDescriptions = is_array($context['group_descriptions'] ?? null) ? $context['group_descriptions'] : [];
            $groupDescription = is_array($groupDescriptions[$targetId] ?? null) ? $groupDescriptions[$targetId] : [];

            return $this->registry->resolve(new ReferenceDescriptor(
                referenceClass: ReferenceClass::Group,
                rawIdentifier: $targetId,
                tenantId: is_numeric($context['managed_environment_id'] ?? null) ? (int) $context['managed_environment_id'] : null,
                fallbackLabel: is_string($groupDescription['display_name'] ?? null)
                    ? $groupDescription['display_name']
                    : (is_string($target['group_display_name'] ?? null) ? $target['group_display_name'] : null),
                context: [
                    'cached_display_name' => $groupDescription['display_name'] ?? null,
                    'resolved_from_cache' => $groupDescription['resolved'] ?? null,
                    'source_hint' => 'Captured from assignment evidence',
                ],
            ));
        }

        if ($targetId !== '') {
            return $this->registry->resolve(new ReferenceDescriptor(
                referenceClass: ReferenceClass::Principal,
                rawIdentifier: $targetId,
                fallbackLabel: is_string($context['fallback_label'] ?? null) ? $context['fallback_label'] : null,
                context: [
                    'principal_type' => $context['principal_type'] ?? $targetType,
                    'secondary_label' => 'Assignment target',
                    'source_hint' => 'Captured from assignment evidence',
                ],
            ));
        }

        return $this->registry->resolve(new ReferenceDescriptor(
            referenceClass: ReferenceClass::Unsupported,
            rawIdentifier: 'assignment_target',
            fallbackLabel: 'Assignment target',
            context: [
                'secondary_label' => 'Assignment target',
                'source_hint' => 'Captured from assignment evidence',
            ],
        ));
    }
}
