<?php

use App\Contracts\Hardening\WriteGateInterface;
use App\Exceptions\Hardening\ProviderAccessHardeningRequired;
use App\Models\ManagedEnvironment;
use Illuminate\Foundation\Testing\RefreshDatabase;

uses(RefreshDatabase::class);

beforeEach(function () {
    config()->set('tenantpilot.hardening.intune_write_gate.enabled', true);
    config()->set('tenantpilot.hardening.intune_write_gate.freshness_threshold_hours', 24);
});

test('gate blocks when rbac_status is ok but rbac_last_checked_at is stale', function () {
    $tenant = ManagedEnvironment::factory()->create([
        'rbac_status' => 'ok',
        'rbac_last_checked_at' => now()->subHours(25),
    ]);

    $gate = app(WriteGateInterface::class);

    try {
        $gate->evaluate($tenant, 'restore.execute');
        $this->fail('Expected ProviderAccessHardeningRequired to be thrown');
    } catch (ProviderAccessHardeningRequired $e) {
        expect($e->reasonCode)->toBe('intune_rbac.stale')
            ->and($e->tenantId)->toBe((int) $tenant->getKey());
    }
});

test('gate blocks when rbac_status is ok but rbac_last_checked_at is null', function () {
    $tenant = ManagedEnvironment::factory()->create([
        'rbac_status' => 'ok',
        'rbac_last_checked_at' => null,
    ]);

    $gate = app(WriteGateInterface::class);

    try {
        $gate->evaluate($tenant, 'restore.execute');
        $this->fail('Expected ProviderAccessHardeningRequired to be thrown');
    } catch (ProviderAccessHardeningRequired $e) {
        expect($e->reasonCode)->toBe('intune_rbac.stale');
    }
});

test('gate blocks at exact threshold boundary', function () {
    $tenant = ManagedEnvironment::factory()->create([
        'rbac_status' => 'ok',
        'rbac_last_checked_at' => now()->subHours(24),
    ]);

    $gate = app(WriteGateInterface::class);

    try {
        $gate->evaluate($tenant, 'restore.execute');
        $this->fail('Expected ProviderAccessHardeningRequired to be thrown');
    } catch (ProviderAccessHardeningRequired $e) {
        expect($e->reasonCode)->toBe('intune_rbac.stale');
    }
});

test('gate respects custom freshness threshold', function () {
    config()->set('tenantpilot.hardening.intune_write_gate.freshness_threshold_hours', 1);

    $tenant = ManagedEnvironment::factory()->create([
        'rbac_status' => 'ok',
        'rbac_last_checked_at' => now()->subHours(2),
    ]);

    $gate = app(WriteGateInterface::class);

    try {
        $gate->evaluate($tenant, 'restore.execute');
        $this->fail('Expected ProviderAccessHardeningRequired to be thrown');
    } catch (ProviderAccessHardeningRequired $e) {
        expect($e->reasonCode)->toBe('intune_rbac.stale');
    }
});
