<?php

declare(strict_types=1);

namespace Tests\Feature\Concerns;

use App\Models\InventoryItem;
use App\Models\Policy;
use App\Models\PolicyVersion;
use App\Models\ManagedEnvironment;
use App\Models\User;
use App\Models\Workspace;
use App\Services\Auth\CapabilityResolver;
use App\Services\Auth\WorkspaceCapabilityResolver;
use App\Support\Workspaces\WorkspaceContext;
use Filament\Facades\Filament;

trait BuildsPortfolioCompareFixtures
{
    /**
     * @return array{user: User, workspace: Workspace, sourceEnvironment: ManagedEnvironment, targetEnvironment: ManagedEnvironment}
     */
    protected function makeCrossEnvironmentCompareFixture(
        string $workspaceRole = 'owner',
        string $tenantRole = 'owner',
    ): array {
        $sourceEnvironment = ManagedEnvironment::factory()->create([
            'name' => 'Source ManagedEnvironment',
        ]);

        [$user, $sourceEnvironment] = createUserWithTenant(
            tenant: $sourceEnvironment,
            role: $tenantRole,
            workspaceRole: $workspaceRole,
        );

        $workspace = Workspace::query()->findOrFail((int) $sourceEnvironment->workspace_id);

        $targetEnvironment = ManagedEnvironment::factory()->create([
            'workspace_id' => (int) $workspace->getKey(),
            'name' => 'Target ManagedEnvironment',
        ]);

        $user->tenants()->syncWithoutDetaching([
            (int) $targetEnvironment->getKey() => ['role' => $tenantRole],
        ]);

        app(CapabilityResolver::class)->clearCache();
        app(WorkspaceCapabilityResolver::class)->clearCache();

        return [
            'user' => $user,
            'workspace' => $workspace,
            'sourceEnvironment' => $sourceEnvironment,
            'targetEnvironment' => $targetEnvironment,
        ];
    }

    /**
     * @return array{0: string, 1: array<string, mixed>}
     */
    protected function setAdminWorkspaceContext(User $user, Workspace $workspace): array
    {
        $this->actingAs($user);

        Filament::setCurrentPanel('admin');
        Filament::setTenant(null, true);
        Filament::bootCurrentPanel();

        session()->put(WorkspaceContext::SESSION_KEY, (int) $workspace->getKey());

        return [WorkspaceContext::SESSION_KEY => (int) $workspace->getKey()];
    }

    /**
     * @param  array<string, mixed>  $snapshot
     * @return array{policy: Policy, version: PolicyVersion, inventory: InventoryItem}
     */
    protected function createPortfolioCompareSubject(
        ManagedEnvironment $tenant,
        string $displayName,
        array $snapshot,
        string $policyType = 'deviceConfiguration',
        ?string $externalId = null,
    ): array {
        $policy = Policy::factory()->create([
            'managed_environment_id' => (int) $tenant->getKey(),
            'policy_type' => $policyType,
            'external_id' => $externalId ?? str($displayName)->slug()->append('-')->append((string) str()->uuid())->toString(),
            'display_name' => $displayName,
            'platform' => 'windows',
        ]);

        $version = PolicyVersion::factory()->create([
            'managed_environment_id' => (int) $tenant->getKey(),
            'policy_id' => (int) $policy->getKey(),
            'policy_type' => $policyType,
            'platform' => 'windows',
            'captured_at' => now(),
            'snapshot' => $snapshot,
            'assignments' => [],
            'scope_tags' => [],
        ]);

        $inventory = InventoryItem::factory()->create([
            'managed_environment_id' => (int) $tenant->getKey(),
            'policy_type' => $policyType,
            'external_id' => (string) $policy->external_id,
            'display_name' => $displayName,
            'last_seen_at' => now(),
        ]);

        return [
            'policy' => $policy,
            'version' => $version,
            'inventory' => $inventory,
        ];
    }
}