<?php

declare(strict_types=1);

use App\Models\ManagedEnvironment;
use App\Models\User;
use App\Models\Workspace;
use App\Models\WorkspaceMembership;
use App\Services\Auth\ManagedEnvironmentMembershipManager;
use App\Services\Auth\WorkspaceMembershipManager;
use App\Support\Auth\Capabilities;
use App\Support\Auth\WorkspaceRole;
use Illuminate\Support\Facades\Gate;

it('gates workspace membership management as owner only', function (): void {
    $workspace = Workspace::factory()->create();

    foreach (WorkspaceRole::cases() as $role) {
        $user = User::factory()->create();

        WorkspaceMembership::factory()->create([
            'workspace_id' => (int) $workspace->getKey(),
            'user_id' => (int) $user->getKey(),
            'role' => $role->value,
        ]);

        expect(Gate::forUser($user)->allows(Capabilities::WORKSPACE_MEMBERSHIP_VIEW, $workspace))->toBe($role !== WorkspaceRole::Readonly);
        expect(Gate::forUser($user)->allows(Capabilities::WORKSPACE_MEMBERSHIP_MANAGE, $workspace))->toBe($role === WorkspaceRole::Owner);
    }
});

it('denies non-owner workspace membership service mutations', function (string $role): void {
    $workspace = Workspace::factory()->create();
    $actor = User::factory()->create();
    $member = User::factory()->create();

    WorkspaceMembership::factory()->create([
        'workspace_id' => (int) $workspace->getKey(),
        'user_id' => (int) $actor->getKey(),
        'role' => $role,
    ]);

    app(WorkspaceMembershipManager::class)->addMember(
        workspace: $workspace,
        actor: $actor,
        member: $member,
        role: WorkspaceRole::Readonly->value,
    );
})->throws(\DomainException::class, 'Forbidden.')->with([
    'manager' => [WorkspaceRole::Manager->value],
    'operator' => [WorkspaceRole::Operator->value],
    'readonly' => [WorkspaceRole::Readonly->value],
]);

it('allows owner workspace membership service mutations', function (): void {
    $workspace = Workspace::factory()->create();
    $owner = User::factory()->create();
    $member = User::factory()->create();

    WorkspaceMembership::factory()->create([
        'workspace_id' => (int) $workspace->getKey(),
        'user_id' => (int) $owner->getKey(),
        'role' => WorkspaceRole::Owner->value,
    ]);

    $membership = app(WorkspaceMembershipManager::class)->addMember(
        workspace: $workspace,
        actor: $owner,
        member: $member,
        role: WorkspaceRole::Readonly->value,
    );

    expect($membership->workspace_id)->toBe((int) $workspace->getKey())
        ->and($membership->user_id)->toBe((int) $member->getKey())
        ->and($membership->role)->toBe(WorkspaceRole::Readonly->value);
});

it('denies manager managed-environment access-scope management', function (): void {
    $workspace = Workspace::factory()->create();
    $tenant = ManagedEnvironment::factory()->active()->create([
        'workspace_id' => (int) $workspace->getKey(),
    ]);
    $manager = User::factory()->create();
    $member = User::factory()->create();

    WorkspaceMembership::factory()->create([
        'workspace_id' => (int) $workspace->getKey(),
        'user_id' => (int) $manager->getKey(),
        'role' => WorkspaceRole::Manager->value,
    ]);
    WorkspaceMembership::factory()->create([
        'workspace_id' => (int) $workspace->getKey(),
        'user_id' => (int) $member->getKey(),
        'role' => WorkspaceRole::Readonly->value,
    ]);

    app(ManagedEnvironmentMembershipManager::class)->grantScope(
        tenant: $tenant,
        actor: $manager,
        member: $member,
    );
})->throws(\DomainException::class, 'Forbidden.');
