<?php

declare(strict_types=1);

namespace App\Filament\Pages;

use App\Models\User;
use App\Models\Workspace;
use App\Models\WorkspaceMembership;
use App\Services\Audit\WorkspaceAuditLogger;
use App\Support\Audit\AuditActionId;
use App\Support\Workspaces\WorkspaceContext;
use App\Support\Workspaces\WorkspaceIntendedUrl;
use App\Support\Workspaces\WorkspaceRedirectResolver;
use Filament\Notifications\Notification;
use Filament\Pages\Page;
use Illuminate\Database\Eloquent\Collection;

class ChooseWorkspace extends Page
{
    protected static string $layout = 'filament-panels::components.layout.simple';

    protected static bool $shouldRegisterNavigation = false;

    protected static bool $isDiscovered = false;

    protected static ?string $slug = 'choose-workspace';

    protected static ?string $title = 'Choose workspace';

    protected string $view = 'filament.pages.choose-workspace';

    /**
     * Workspace roles keyed by workspace_id.
     *
     * @var array<int, string>
     */
    public array $workspaceRoles = [];

    /**
     * @return array<\Filament\Actions\Action>
     */
    protected function getHeaderActions(): array
    {
        return [];
    }

    /**
     * @return Collection<int, Workspace>
     */
    public function getWorkspaces(): Collection
    {
        $user = auth()->user();

        if (! $user instanceof User) {
            return Workspace::query()->whereRaw('1 = 0')->get();
        }

        $workspaces = Workspace::query()
            ->whereIn('id', function ($query) use ($user): void {
                $query->from('workspace_memberships')
                    ->select('workspace_id')
                    ->where('user_id', $user->getKey());
            })
            ->whereNull('archived_at')
            ->whereNull('closed_at')
            ->withCount(['tenants' => function ($query): void {
                $query->where('lifecycle_status', 'active')
                    ->whereNull('removed_from_workspace_at');
            }])
            ->orderBy('name')
            ->get();

        // Build roles map from memberships.
        $memberships = WorkspaceMembership::query()
            ->where('user_id', $user->getKey())
            ->whereIn('workspace_id', $workspaces->pluck('id'))
            ->pluck('role', 'workspace_id');

        $this->workspaceRoles = $memberships->mapWithKeys(fn ($role, $id) => [(int) $id => (string) $role])->all();

        return $workspaces;
    }

    public function selectWorkspace(int $workspaceId): void
    {
        $user = auth()->user();

        if (! $user instanceof User) {
            abort(403);
        }

        $workspace = Workspace::query()->whereKey($workspaceId)->first();

        if (! $workspace instanceof Workspace) {
            abort(404);
        }

        if (! $workspace->isSelectableAsContext()) {
            abort(404);
        }

        $context = app(WorkspaceContext::class);

        if (! $context->isMember($user, $workspace)) {
            abort(404);
        }

        $prevWorkspaceId = $context->currentWorkspaceId(request());

        $context->setCurrentWorkspace($workspace, $user, request());

        // Audit: manual workspace selection.
        /** @var WorkspaceAuditLogger $logger */
        $logger = app(WorkspaceAuditLogger::class);

        $logger->log(
            workspace: $workspace,
            action: AuditActionId::WorkspaceSelected->value,
            context: [
                'metadata' => [
                    'method' => 'manual',
                    'reason' => 'chooser',
                    'prev_workspace_id' => $prevWorkspaceId,
                ],
            ],
            actor: $user,
            resourceType: 'workspace',
            resourceId: (string) $workspace->getKey(),
        );

        /** @var WorkspaceRedirectResolver $resolver */
        $resolver = app(WorkspaceRedirectResolver::class);

        $redirectTarget = $resolver->resolve(
            $workspace,
            $user,
            WorkspaceIntendedUrl::consume(request()),
        );

        $this->redirect($redirectTarget);
    }

    /**
     * @param  array{name: string, slug?: string|null}  $data
     */
    public function createWorkspace(array $data): void
    {
        $user = auth()->user();

        if (! $user instanceof User) {
            abort(403);
        }

        if (! $user->can('create', Workspace::class)) {
            abort(403);
        }

        $workspace = Workspace::query()->create([
            'name' => $data['name'],
            'slug' => $data['slug'] ?? null,
        ]);

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

        app(WorkspaceContext::class)->setCurrentWorkspace($workspace, $user, request());

        Notification::make()
            ->title('Workspace created')
            ->success()
            ->send();

        /** @var WorkspaceRedirectResolver $resolver */
        $resolver = app(WorkspaceRedirectResolver::class);

        $redirectTarget = $resolver->resolve(
            $workspace,
            $user,
            WorkspaceIntendedUrl::consume(request()),
        );

        $this->redirect($redirectTarget);
    }
}
