<?php

namespace App\Services\Graph;

use App\Models\ManagedEnvironment;
use App\Services\Providers\ProviderConnectionResolver;
use App\Services\Providers\ProviderGateway;
use Illuminate\Support\Facades\Cache;

class ScopeTagResolver
{
    public function __construct(
        private readonly ProviderConnectionResolver $providerConnections,
        private readonly ProviderGateway $providerGateway,
    ) {}

    /**
     * Resolve scope tag IDs to scope tag objects.
     *
     * Fetches all scope tags from tenant and caches for 1 hour.
     * Filters to requested IDs in memory.
     *
     * @param  array  $scopeTagIds  Array of scope tag IDs to resolve
     * @param  ManagedEnvironment|null  $tenant  Optional tenant model with credentials
     * @return array Array of scope tag objects with id and displayName
     */
    public function resolve(array $scopeTagIds, ?ManagedEnvironment $tenant = null): array
    {
        if (empty($scopeTagIds)) {
            return [];
        }

        // Fetch all scope tags (cached)
        $allScopeTags = $this->fetchAllScopeTags($tenant);

        // Filter to requested IDs
        return array_filter($allScopeTags, function ($scopeTag) use ($scopeTagIds) {
            return in_array($scopeTag['id'], $scopeTagIds);
        });
    }

    /**
     * Fetch all scope tags from Graph API (cached for 1 hour).
     */
    private function fetchAllScopeTags(?ManagedEnvironment $tenant = null): array
    {
        if (! $tenant instanceof ManagedEnvironment) {
            return [];
        }

        $cacheKey = $tenant ? "scope_tags:tenant:{$tenant->id}" : 'scope_tags:all';

        return Cache::remember($cacheKey, 3600, function () use ($tenant) {
            try {
                $resolution = $this->providerConnections->resolveDefault($tenant, 'microsoft');

                if (! $resolution->resolved || $resolution->connection === null) {
                    \Log::warning('Scope tag fetch blocked: provider connection unavailable', [
                        'managed_environment_id' => $tenant->id,
                        'reason_code' => $resolution->effectiveReasonCode(),
                    ]);

                    return [];
                }

                $graphResponse = $this->providerGateway->request(
                    $resolution->connection,
                    'GET',
                    '/deviceManagement/roleScopeTags',
                    ['query' => ['$select' => 'id,displayName']]
                );

                $scopeTags = $graphResponse->data['value'] ?? [];

                // Check for 403 Forbidden (missing permissions)
                if (! $graphResponse->success && $graphResponse->status === 403) {
                    \Log::warning('Scope tag fetch failed: Missing permissions', [
                        'managed_environment_id' => $tenant?->id,
                        'status' => 403,
                        'required_permissions' => ['DeviceManagementRBAC.Read.All', 'DeviceManagementRBAC.ReadWrite.All'],
                        'message' => 'App registration needs DeviceManagementRBAC permissions to read scope tags',
                    ]);
                }

                // Success - return scope tags
                return $scopeTags;
            } catch (\Exception $e) {
                // Fail soft - return empty array on any error
                \Log::warning('Scope tag fetch exception', [
                    'managed_environment_id' => $tenant?->id,
                    'error' => $e->getMessage(),
                ]);

                return [];
            }
        });
    }
}
