<?php

use App\Models\ManagedEnvironment;
use App\Models\Policy;
use App\Models\PolicyVersion;
use App\Models\ProviderConnection;
use App\Models\ProviderCredential;
use App\Models\Workspace;
use App\Services\Graph\GraphClientInterface;
use App\Services\Graph\GraphResponse;
use App\Services\Intune\PolicySyncService;
use Carbon\CarbonImmutable;
use Illuminate\Foundation\Testing\RefreshDatabase;

uses(RefreshDatabase::class);

class SettingsCatalogFakeGraphClient implements GraphClientInterface
{
    /**
     * @param  array<string, GraphResponse>  $responses
     */
    public function __construct(private array $responses = []) {}

    public function listPolicies(string $policyType, array $options = []): GraphResponse
    {
        return $this->responses[$policyType] ?? new GraphResponse(true, []);
    }

    public function getPolicy(string $policyType, string $policyId, array $options = []): GraphResponse
    {
        return new GraphResponse(true, []);
    }

    public function getOrganization(array $options = []): GraphResponse
    {
        return new GraphResponse(true, []);
    }

    public function applyPolicy(string $policyType, string $policyId, array $payload, array $options = []): GraphResponse
    {
        return new GraphResponse(true, []);
    }

    public function getServicePrincipalPermissions(array $options = []): GraphResponse
    {
        return new GraphResponse(true, []);
    }

    public function request(string $method, string $path, array $options = []): GraphResponse
    {
        return new GraphResponse(true, []);
    }
}

test('settings catalog policies sync as their own type and render in the list', function () {
    $responses = [
        'deviceConfiguration' => new GraphResponse(true, [
            [
                'id' => 'config-1',
                'displayName' => 'Device Config 1',
                'platform' => 'windows',
            ],
        ]),
        'settingsCatalogPolicy' => new GraphResponse(true, [
            [
                'id' => 'scp-1',
                'name' => 'Settings Catalog Alpha',
                'platform' => 'windows',
                '@odata.type' => '#microsoft.graph.deviceManagementConfigurationPolicy',
                'settings' => [
                    ['displayName' => 'Setting A', 'value' => 'on'],
                ],
            ],
        ]),
    ];

    app()->instance(GraphClientInterface::class, new SettingsCatalogFakeGraphClient($responses));

    $tenant = ManagedEnvironment::create([
        'managed_environment_id' => 'local-tenant',
        'name' => 'ManagedEnvironment One',
        'metadata' => [],
        'is_current' => true,
    ]);
    $tenant->makeCurrent();
    expect(ManagedEnvironment::current()->id)->toBe($tenant->id);

    $workspace = Workspace::factory()->create();
    $tenant->forceFill(['workspace_id' => (int) $workspace->getKey()])->save();

    $connection = ProviderConnection::factory()->consentGranted()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'workspace_id' => (int) $workspace->getKey(),
        'provider' => 'microsoft',
        'entra_tenant_id' => $tenant->managed_environment_id,
        'is_default' => true,
        'consent_status' => 'granted',
    ]);

    ProviderCredential::factory()->create([
        'provider_connection_id' => (int) $connection->getKey(),
        'type' => 'client_secret',
        'payload' => [
            'client_id' => 'test-client-id',
            'client_secret' => 'test-client-secret',
        ],
    ]);

    app(PolicySyncService::class)->syncPolicies($tenant);

    $settingsPolicy = Policy::where('policy_type', 'settingsCatalogPolicy')->first();

    expect($settingsPolicy)->not->toBeNull();
    expect($settingsPolicy->display_name)->toBe('Settings Catalog Alpha');
    expect($settingsPolicy->platform)->toBe('windows');

    expect(Policy::where('policy_type', 'deviceConfiguration')->count())->toBe(1);
    expect(Policy::where('policy_type', 'deviceConfiguration')->where('external_id', 'scp-1')->exists())->toBeFalse();

    PolicyVersion::create([
        'managed_environment_id' => $tenant->id,
        'policy_id' => $settingsPolicy->id,
        'version_number' => 1,
        'policy_type' => $settingsPolicy->policy_type,
        'platform' => $settingsPolicy->platform,
        'created_by' => 'tester@example.com',
        'captured_at' => CarbonImmutable::now(),
        'snapshot' => [
            '@odata.type' => '#microsoft.graph.deviceManagementConfigurationPolicy',
            'settings' => [
                ['displayName' => 'Setting A', 'value' => 'on'],
            ],
        ],
    ]);

    [$user, $tenant] = createUserWithTenant($tenant, role: 'owner');

    $response = $this
        ->actingAs($user)
        ->withSession([
            \App\Support\Workspaces\WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id,
            \App\Support\Workspaces\WorkspaceContext::LAST_ENVIRONMENT_IDS_SESSION_KEY => [
                (string) $tenant->workspace_id => (int) $tenant->getKey(),
            ],
        ])
        ->get(\App\Filament\Resources\PolicyResource::getUrl(panel: 'admin', tenant: $tenant));

    $response->assertOk();
    $response->assertSee('Settings Catalog Policy');
    $response->assertSee('Settings Catalog Alpha');
    $response->assertSee('Available');
});
