<?php

namespace App\Livewire;

use App\Models\PolicyVersion;
use App\Models\ManagedEnvironment;
use App\Services\Directory\EntraGroupLabelResolver;
use App\Support\References\ReferencePresentationVariant;
use App\Support\References\ResolvedReferencePresenter;
use App\Support\References\Resolvers\AssignmentTargetReferenceResolver;
use Livewire\Component;

class PolicyVersionAssignmentsWidget extends Component
{
    public PolicyVersion $version;

    public function mount(PolicyVersion $version): void
    {
        $this->version = $version;
    }

    public function render(): \Illuminate\Contracts\View\View
    {
        return view('livewire.policy-version-assignments-widget', [
            'version' => $this->version,
            'compliance' => $this->complianceNotifications(),
            'assignmentReferences' => $this->assignmentReferences(),
        ]);
    }

    /**
     * @return array<int, array<string, mixed>>
     */
    private function assignmentReferences(): array
    {
        $assignments = $this->version->assignments;

        if (! is_array($assignments) || $assignments === []) {
            return [];
        }

        $tenant = rescue(fn () => ManagedEnvironment::current(), null);

        if (! $tenant instanceof ManagedEnvironment) {
            $this->version->loadMissing('tenant');

            $tenant = $this->version->tenant instanceof ManagedEnvironment
                ? $this->version->tenant
                : null;
        }

        $groupIds = [];
        $sourceNames = [];

        foreach ($assignments as $assignment) {
            if (! is_array($assignment)) {
                continue;
            }

            $target = $assignment['target'] ?? null;

            if (! is_array($target)) {
                continue;
            }

            $groupId = $target['groupId'] ?? null;

            if (! is_string($groupId) || $groupId === '') {
                continue;
            }

            $groupIds[] = $groupId;

            $displayName = $target['group_display_name'] ?? null;

            if (is_string($displayName) && $displayName !== '') {
                $sourceNames[$groupId] = $displayName;
            }
        }

        $groupIds = array_values(array_unique($groupIds));

        $groupDescriptions = [];

        if ($tenant instanceof ManagedEnvironment && $groupIds !== []) {
            $resolver = app(EntraGroupLabelResolver::class);
            $groupDescriptions = $resolver->describeMany($tenant, $groupIds, $sourceNames);
        } else {
            foreach ($groupIds as $groupId) {
                $groupDescriptions[$groupId] = [
                    'display_name' => $sourceNames[$groupId] ?? null,
                    'resolved' => false,
                ];
            }
        }

        $references = [];
        $assignmentTargetResolver = app(AssignmentTargetReferenceResolver::class);
        $presenter = app(ResolvedReferencePresenter::class);

        foreach ($assignments as $index => $assignment) {
            if (! is_array($assignment)) {
                continue;
            }

            $target = $assignment['target'] ?? null;

            if (! is_array($target)) {
                continue;
            }

            $type = strtolower((string) ($target['@odata.type'] ?? ''));
            $targetId = (string) ($target['groupId'] ?? $target['collectionId'] ?? '');

            $references[$index] = $presenter->present(
                $assignmentTargetResolver->resolve($target, [
                    'managed_environment_id' => $tenant?->getKey(),
                    'target_type' => $type,
                    'target_id' => $targetId,
                    'group_descriptions' => $groupDescriptions,
                    'fallback_label' => is_string($target['group_display_name'] ?? null) ? $target['group_display_name'] : null,
                ]),
                ReferencePresentationVariant::Compact,
            );
        }

        return $references;
    }

    /**
     * @return array{total:int,templates:array<int,string>,items:array<int,array{rule_name:?string,template_id:string,template_key:string}>}
     */
    private function complianceNotifications(): array
    {
        if ($this->version->policy_type !== 'deviceCompliancePolicy') {
            return [
                'total' => 0,
                'templates' => [],
                'items' => [],
            ];
        }

        $snapshot = $this->version->snapshot;

        if (! is_array($snapshot)) {
            return [
                'total' => 0,
                'templates' => [],
                'items' => [],
            ];
        }

        $scheduled = $snapshot['scheduledActionsForRule'] ?? null;

        if (! is_array($scheduled)) {
            return [
                'total' => 0,
                'templates' => [],
                'items' => [],
            ];
        }

        $items = [];
        $templateIds = [];

        foreach ($scheduled as $rule) {
            if (! is_array($rule)) {
                continue;
            }

            $ruleName = $rule['ruleName'] ?? null;
            $configs = $rule['scheduledActionConfigurations'] ?? null;

            if (! is_array($configs)) {
                continue;
            }

            foreach ($configs as $config) {
                if (! is_array($config)) {
                    continue;
                }

                if (($config['actionType'] ?? null) !== 'notification') {
                    continue;
                }

                $templateKey = $this->resolveNotificationTemplateKey($config);

                if ($templateKey === null) {
                    continue;
                }

                $templateId = $config[$templateKey] ?? null;

                if (! is_string($templateId) || $templateId === '' || $this->isEmptyGuid($templateId)) {
                    continue;
                }

                $items[] = [
                    'rule_name' => is_string($ruleName) ? $ruleName : null,
                    'template_id' => $templateId,
                    'template_key' => $templateKey,
                ];
                $templateIds[] = $templateId;
            }
        }

        return [
            'total' => count($items),
            'templates' => array_values(array_unique($templateIds)),
            'items' => $items,
        ];
    }

    private function resolveNotificationTemplateKey(array $config): ?string
    {
        if (array_key_exists('notificationTemplateId', $config)) {
            return 'notificationTemplateId';
        }

        if (array_key_exists('notificationMessageTemplateId', $config)) {
            return 'notificationMessageTemplateId';
        }

        return null;
    }

    private function isEmptyGuid(string $value): bool
    {
        return strtolower($value) === '00000000-0000-0000-0000-000000000000';
    }
}
