<?php

use App\Models\BackupItem;
use App\Models\BackupSchedule;
use App\Models\BackupSet;
use App\Models\EntraGroup;
use App\Models\EntraRoleDefinition;
use App\Models\Finding;
use App\Models\InventoryItem;
use App\Models\InventoryLink;
use App\Models\Policy;
use App\Models\PolicyVersion;
use App\Models\RestoreRun;
use App\Models\ManagedEnvironment;
use App\Models\ManagedEnvironmentPermission;
use App\Models\Workspace;
use App\Support\WorkspaceIsolation\WorkspaceIsolationViolation;
use Illuminate\Foundation\Testing\RefreshDatabase;

uses(RefreshDatabase::class);

it('enforces tenant workspace binding for tenant-owned models even when events are disabled', function (): void {
    $workspaceA = Workspace::factory()->create();
    $workspaceB = Workspace::factory()->create();

    $tenant = ManagedEnvironment::factory()->create([
        'workspace_id' => $workspaceA->getKey(),
    ]);

    $policy = Policy::factory()->create([
        'managed_environment_id' => $tenant->getKey(),
        'workspace_id' => $workspaceA->getKey(),
    ]);

    $backupSet = BackupSet::factory()->create([
        'managed_environment_id' => $tenant->getKey(),
        'workspace_id' => $workspaceA->getKey(),
    ]);

    $cases = [
        'policies' => fn (int $workspaceId) => Policy::factory()->make([
            'managed_environment_id' => $tenant->getKey(),
            'workspace_id' => $workspaceId,
        ]),
        'policy_versions' => fn (int $workspaceId) => PolicyVersion::factory()->make([
            'managed_environment_id' => $tenant->getKey(),
            'workspace_id' => $workspaceId,
            'policy_id' => $policy->getKey(),
        ]),
        'backup_sets' => fn (int $workspaceId) => BackupSet::factory()->make([
            'managed_environment_id' => $tenant->getKey(),
            'workspace_id' => $workspaceId,
        ]),
        'backup_items' => fn (int $workspaceId) => BackupItem::factory()->make([
            'managed_environment_id' => $tenant->getKey(),
            'workspace_id' => $workspaceId,
            'backup_set_id' => $backupSet->getKey(),
            'policy_id' => $policy->getKey(),
        ]),
        'restore_runs' => fn (int $workspaceId) => RestoreRun::factory()->make([
            'managed_environment_id' => $tenant->getKey(),
            'workspace_id' => $workspaceId,
            'backup_set_id' => $backupSet->getKey(),
        ]),
        'backup_schedules' => fn (int $workspaceId) => BackupSchedule::make([
            'managed_environment_id' => $tenant->getKey(),
            'workspace_id' => $workspaceId,
            'name' => 'Weekly backup',
            'is_enabled' => true,
            'timezone' => 'UTC',
            'frequency' => 'daily',
            'time_of_day' => '00:00:00',
            'days_of_week' => null,
            'policy_types' => ['settingsCatalogPolicy'],
            'include_foundations' => true,
            'retention_keep_last' => 30,
        ]),
        'inventory_items' => fn (int $workspaceId) => InventoryItem::factory()->make([
            'managed_environment_id' => $tenant->getKey(),
            'workspace_id' => $workspaceId,
        ]),
        'inventory_links' => fn (int $workspaceId) => InventoryLink::factory()->make([
            'managed_environment_id' => $tenant->getKey(),
            'workspace_id' => $workspaceId,
        ]),
        'entra_groups' => fn (int $workspaceId) => EntraGroup::factory()->make([
            'managed_environment_id' => $tenant->getKey(),
            'workspace_id' => $workspaceId,
        ]),
        'findings' => fn (int $workspaceId) => Finding::factory()->make([
            'managed_environment_id' => $tenant->getKey(),
            'workspace_id' => $workspaceId,
        ]),
        'entra_role_definitions' => fn (int $workspaceId) => EntraRoleDefinition::factory()->make([
            'managed_environment_id' => $tenant->getKey(),
            'workspace_id' => $workspaceId,
        ]),
        'managed_environment_permissions' => fn (int $workspaceId) => ManagedEnvironmentPermission::make([
            'managed_environment_id' => $tenant->getKey(),
            'workspace_id' => $workspaceId,
            'permission_key' => 'test.permission.'.uniqid(),
            'status' => 'missing',
        ]),
    ];

    foreach ($cases as $table => $makeModel) {
        $model = $makeModel((int) $workspaceA->getKey());

        ($model::class)::withoutEvents(function () use ($model): void {
            $model->save();
        });

        $this->assertDatabaseHas($table, [
            'managed_environment_id' => $tenant->getKey(),
            'workspace_id' => $workspaceA->getKey(),
        ]);

        $mismatched = $makeModel((int) $workspaceB->getKey());

        expect(fn () => $mismatched->save())
            ->toThrow(WorkspaceIsolationViolation::class);
    }
});

it('keeps RBAC foundation policy versions and backup items pinned to the tenant workspace', function (): void {
    $workspace = Workspace::factory()->create();

    $tenant = ManagedEnvironment::factory()->create([
        'workspace_id' => $workspace->getKey(),
    ]);

    $policy = Policy::query()->create([
        'managed_environment_id' => $tenant->getKey(),
        'workspace_id' => $workspace->getKey(),
        'external_id' => 'role-def-1',
        'policy_type' => 'intuneRoleDefinition',
        'platform' => 'all',
        'display_name' => 'Policy and Profile Manager',
        'last_synced_at' => null,
        'metadata' => ['foundation_anchor' => true],
    ]);

    $version = PolicyVersion::query()->create([
        'managed_environment_id' => $tenant->getKey(),
        'workspace_id' => $workspace->getKey(),
        'policy_id' => $policy->getKey(),
        'version_number' => 1,
        'policy_type' => 'intuneRoleDefinition',
        'platform' => 'all',
        'captured_at' => now(),
        'snapshot' => ['displayName' => 'Policy and Profile Manager'],
        'metadata' => ['capture_source' => 'foundation_capture'],
        'secret_fingerprints' => [
            'snapshot' => [],
            'assignments' => [],
            'scope_tags' => [],
        ],
        'redaction_version' => 1,
    ]);

    $backupSet = BackupSet::factory()->create([
        'managed_environment_id' => $tenant->getKey(),
        'workspace_id' => $workspace->getKey(),
    ]);

    $backupItem = BackupItem::query()->create([
        'managed_environment_id' => $tenant->getKey(),
        'workspace_id' => $workspace->getKey(),
        'backup_set_id' => $backupSet->getKey(),
        'policy_id' => $policy->getKey(),
        'policy_version_id' => $version->getKey(),
        'policy_identifier' => 'role-def-1',
        'policy_type' => 'intuneRoleDefinition',
        'platform' => 'all',
        'payload' => ['displayName' => 'Policy and Profile Manager'],
        'metadata' => ['displayName' => 'Policy and Profile Manager'],
    ]);

    expect((int) $version->workspace_id)->toBe((int) $workspace->getKey());
    expect((int) $backupItem->workspace_id)->toBe((int) $workspace->getKey());
});
