<?php

declare(strict_types=1);

use App\Models\AuditLog;
use App\Models\User;
use App\Models\Workspace;
use App\Models\WorkspaceMembership;
use App\Services\Auth\WorkspaceMembershipManager;
use App\Support\Auth\WorkspaceRole;
use Illuminate\Foundation\Testing\RefreshDatabase;

uses(RefreshDatabase::class);

it('blocks demoting the last remaining workspace owner and audits it', function () {
    $workspace = Workspace::factory()->create();

    $actor = User::factory()->create();
    $target = User::factory()->create();

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

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

    $manager = app(WorkspaceMembershipManager::class);

    expect(fn () => $manager->changeRole($workspace, $actor, $targetMembership, WorkspaceRole::Manager->value))
        ->toThrow(DomainException::class, 'You cannot demote the last remaining owner.');

    $targetMembership->refresh();
    expect($targetMembership->role)->toBe(WorkspaceRole::Owner->value);

    $audit = AuditLog::query()
        ->where('workspace_id', $workspace->getKey())
        ->where('action', 'workspace_membership.last_owner_blocked')
        ->where('status', 'blocked')
        ->latest('id')
        ->first();

    expect($audit)->not->toBeNull();
    expect($audit->metadata)->toMatchArray([
        'workspace_id' => (int) $workspace->getKey(),
        'actor_user_id' => (int) $actor->getKey(),
        'target_user_id' => (int) $target->getKey(),
        'attempted_role' => WorkspaceRole::Manager->value,
    ]);
});

it('blocks removing the last remaining workspace owner and audits it', function () {
    $workspace = Workspace::factory()->create();

    $actor = User::factory()->create();
    $target = User::factory()->create();

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

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

    $manager = app(WorkspaceMembershipManager::class);

    expect(fn () => $manager->removeMember($workspace, $actor, $targetMembership))
        ->toThrow(DomainException::class, 'You cannot remove the last remaining owner.');

    expect(WorkspaceMembership::query()->whereKey($targetMembership->getKey())->exists())->toBeTrue();

    $audit = AuditLog::query()
        ->where('workspace_id', $workspace->getKey())
        ->where('action', 'workspace_membership.last_owner_blocked')
        ->where('status', 'blocked')
        ->latest('id')
        ->first();

    expect($audit)->not->toBeNull();
    expect($audit->metadata)->toMatchArray([
        'workspace_id' => (int) $workspace->getKey(),
        'actor_user_id' => (int) $actor->getKey(),
        'target_user_id' => (int) $target->getKey(),
        'attempted_action' => 'remove',
    ]);
});
