<?php

use App\Models\Policy;
use App\Models\PolicyVersion;
use App\Models\ManagedEnvironment;
use App\Services\Graph\GraphClientInterface;
use App\Services\Graph\GraphResponse;
use Carbon\CarbonImmutable;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Mockery\MockInterface;

uses(RefreshDatabase::class);

test('reclassify command moves ESP versions out of enrollmentRestriction', function () {
    $tenant = ManagedEnvironment::create([
        'managed_environment_id' => 'tenant-reclassify',
        'name' => 'ManagedEnvironment Reclassify',
        'metadata' => [],
        'is_current' => true,
    ]);

    $tenant->makeCurrent();

    $policy = Policy::create([
        'managed_environment_id' => $tenant->id,
        'external_id' => 'esp-1',
        'policy_type' => 'enrollmentRestriction',
        'display_name' => 'ESP Misclassified',
        'platform' => 'all',
    ]);

    $version = PolicyVersion::create([
        'managed_environment_id' => $tenant->id,
        'policy_id' => $policy->id,
        'version_number' => 1,
        'policy_type' => 'enrollmentRestriction',
        'platform' => 'all',
        'created_by' => 'tester@example.com',
        'captured_at' => CarbonImmutable::now(),
        'snapshot' => [
            '@odata.type' => '#microsoft.graph.windows10EnrollmentCompletionPageConfiguration',
            'deviceEnrollmentConfigurationType' => 'windows10EnrollmentCompletionPageConfiguration',
            'displayName' => 'ESP Misclassified',
        ],
    ]);

    $this->artisan('intune:reclassify-enrollment-configurations', ['--tenant' => $tenant->managed_environment_id])
        ->assertSuccessful();

    $version->refresh();
    $policy->refresh();

    expect($version->policy_type)->toBe('enrollmentRestriction');
    expect($policy->policy_type)->toBe('enrollmentRestriction');

    $this->artisan('intune:reclassify-enrollment-configurations', ['--tenant' => $tenant->managed_environment_id, '--write' => true])
        ->assertSuccessful();

    $version->refresh();
    $policy->refresh();

    expect($version->policy_type)->toBe('windowsEnrollmentStatusPage');
    expect($policy->policy_type)->toBe('windowsEnrollmentStatusPage');
    expect($policy->missing_from_provider_at)->toBeNull();
});

test('reclassify command can detect ESP even when a policy has no versions', function () {
    $tenant = ManagedEnvironment::create([
        'managed_environment_id' => 'tenant-reclassify-no-versions',
        'name' => 'ManagedEnvironment Reclassify (No Versions)',
        'metadata' => [],
        'is_current' => true,
    ]);

    $tenant->makeCurrent();

    $policy = Policy::create([
        'managed_environment_id' => $tenant->id,
        'external_id' => 'esp-2',
        'policy_type' => 'enrollmentRestriction',
        'display_name' => 'ESP Misclassified (No Versions)',
        'platform' => 'all',
    ]);

    $this->mock(GraphClientInterface::class, function (MockInterface $mock) {
        $mock->shouldReceive('getPolicy')
            ->andReturn(new GraphResponse(true, [
                'payload' => [
                    '@odata.type' => '#microsoft.graph.windows10EnrollmentCompletionPageConfiguration',
                    'deviceEnrollmentConfigurationType' => 'windows10EnrollmentCompletionPageConfiguration',
                    'displayName' => 'ESP Misclassified (No Versions)',
                ],
            ]));
    });

    $this->artisan('intune:reclassify-enrollment-configurations', ['--tenant' => $tenant->managed_environment_id])
        ->assertSuccessful();

    $policy->refresh();
    expect($policy->policy_type)->toBe('enrollmentRestriction');

    $this->artisan('intune:reclassify-enrollment-configurations', ['--tenant' => $tenant->managed_environment_id, '--write' => true])
        ->assertSuccessful();

    $policy->refresh();
    expect($policy->policy_type)->toBe('windowsEnrollmentStatusPage');
    expect($policy->missing_from_provider_at)->toBeNull();
});

test('reclassify command marks duplicate wrong rows provider missing instead of ignored', function () {
    $tenant = ManagedEnvironment::create([
        'managed_environment_id' => 'tenant-reclassify-duplicate',
        'name' => 'ManagedEnvironment Reclassify Duplicate',
        'metadata' => [],
        'is_current' => true,
    ]);

    $tenant->makeCurrent();

    $wrong = Policy::create([
        'managed_environment_id' => $tenant->id,
        'external_id' => 'esp-duplicate',
        'policy_type' => 'enrollmentRestriction',
        'display_name' => 'ESP Duplicate Wrong',
        'platform' => 'all',
    ]);

    Policy::create([
        'managed_environment_id' => $tenant->id,
        'external_id' => 'esp-duplicate',
        'policy_type' => 'windowsEnrollmentStatusPage',
        'display_name' => 'ESP Duplicate Correct',
        'platform' => 'all',
    ]);

    PolicyVersion::create([
        'managed_environment_id' => $tenant->id,
        'policy_id' => $wrong->id,
        'version_number' => 1,
        'policy_type' => 'enrollmentRestriction',
        'platform' => 'all',
        'created_by' => 'tester@example.com',
        'captured_at' => CarbonImmutable::now(),
        'snapshot' => [
            '@odata.type' => '#microsoft.graph.windows10EnrollmentCompletionPageConfiguration',
            'deviceEnrollmentConfigurationType' => 'windows10EnrollmentCompletionPageConfiguration',
            'displayName' => 'ESP Duplicate Wrong',
        ],
    ]);

    $this->artisan('intune:reclassify-enrollment-configurations', ['--tenant' => $tenant->managed_environment_id, '--write' => true])
        ->assertSuccessful();

    $wrong->refresh();

    expect($wrong->policy_type)->toBe('enrollmentRestriction')
        ->and($wrong->ignored_at)->toBeNull()
        ->and($wrong->missing_from_provider_at)->not->toBeNull();
});
