<?php

namespace App\Services\Graph;

use App\Models\Tenant;
use Illuminate\Support\Facades\Cache;

class ScopeTagResolver
{
    public function __construct(
        private readonly MicrosoftGraphClient $graphClient,
        private readonly GraphLogger $logger,
    ) {}

    /**
     * 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  Tenant|null  $tenant  Optional tenant model with credentials
     * @return array Array of scope tag objects with id and displayName
     */
    public function resolve(array $scopeTagIds, ?Tenant $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(?Tenant $tenant = null): array
    {
        $cacheKey = $tenant ? "scope_tags:tenant:{$tenant->id}" : 'scope_tags:all';
        
        return Cache::remember($cacheKey, 3600, function () use ($tenant) {
            try {
                $options = ['query' => ['$select' => 'id,displayName']];
                
                // Add tenant credentials if provided
                if ($tenant) {
                    $options['tenant'] = $tenant->external_id ?? $tenant->tenant_id;
                    $options['client_id'] = $tenant->app_client_id;
                    $options['client_secret'] = $tenant->app_client_secret;
                }
                
                $graphResponse = $this->graphClient->request(
                    'GET',
                    '/deviceManagement/roleScopeTags',
                    $options
                );

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

                // Check for 403 Forbidden (missing permissions)
                if (! $graphResponse->success && $graphResponse->status === 403) {
                    \Log::warning('Scope tag fetch failed: Missing permissions', [
                        'tenant_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', [
                    'tenant_id' => $tenant?->id,
                    'error' => $e->getMessage(),
                ]);

                return [];
            }
        });
    }
}
