<?php

declare(strict_types=1);

namespace App\Filament\System\Pages;

use App\Filament\System\Widgets\RepairWorkspaceOwnersStats;
use App\Models\AuditLog;
use App\Models\PlatformUser;
use App\Models\SupportAccessGrant;
use App\Models\User;
use App\Models\Workspace;
use App\Models\WorkspaceMembership;
use App\Services\Audit\WorkspaceAuditLogger;
use App\Services\Auth\BreakGlassSession;
use App\Services\Auth\SupportAccessGrantResolver;
use App\Support\Audit\AuditActionId;
use App\Support\Auth\PlatformCapabilities;
use App\Support\Auth\WorkspaceRole;
use Filament\Actions\Action;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\Textarea;
use Filament\Notifications\Notification;
use Filament\Pages\Page;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Concerns\InteractsWithTable;
use Filament\Tables\Contracts\HasTable;
use Filament\Tables\Table;
use Filament\Widgets\Widget;
use Filament\Widgets\WidgetConfiguration;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Validation\ValidationException;

class RepairWorkspaceOwners extends Page implements HasTable
{
    use InteractsWithTable;

    protected static string|\BackedEnum|null $navigationIcon = 'heroicon-o-wrench-screwdriver';

    protected static ?string $navigationLabel = 'Repair workspace owners';

    protected static string|\UnitEnum|null $navigationGroup = 'Recovery';

    protected string $view = 'filament.system.pages.repair-workspace-owners';

    public static function canAccess(): bool
    {
        $user = auth('platform')->user();

        if (! $user instanceof PlatformUser) {
            return false;
        }

        return $user->hasCapability(PlatformCapabilities::USE_BREAK_GLASS);
    }

    public static function getNavigationBadge(): ?string
    {
        $total = Workspace::query()->count();
        $withOwners = WorkspaceMembership::query()
            ->where('role', WorkspaceRole::Owner->value)
            ->distinct('workspace_id')
            ->count('workspace_id');

        $ownerless = $total - $withOwners;

        return $ownerless > 0 ? (string) $ownerless : null;
    }

    public static function getNavigationBadgeColor(): string|array|null
    {
        return 'danger';
    }

    public function mount(): void
    {
        $this->mountInteractsWithTable();
    }

    /**
     * @return array<class-string<Widget>|WidgetConfiguration>
     */
    protected function getHeaderWidgets(): array
    {
        return [
            RepairWorkspaceOwnersStats::class,
        ];
    }

    public function table(Table $table): Table
    {
        return $table
            ->heading('Workspaces')
            ->description('Current workspace ownership status.')
            ->defaultSort('name', 'asc')
            ->paginated(\App\Support\Filament\TablePaginationProfiles::customPage())
            ->query(function (): Builder {
                return Workspace::query()
                    ->withCount([
                        'memberships as owner_count' => function (Builder $query): void {
                            $query->where('role', WorkspaceRole::Owner->value);
                        },
                        'memberships as member_count',
                        'tenants as tenant_count',
                    ]);
            })
            ->columns([
                TextColumn::make('name')
                    ->label('Workspace')
                    ->searchable()
                    ->sortable(),
                TextColumn::make('owner_count')
                    ->label('Owners')
                    ->badge()
                    ->color(fn (int $state): string => $state > 0 ? 'success' : 'danger')
                    ->sortable(),
                TextColumn::make('member_count')
                    ->label('Members')
                    ->sortable(),
                TextColumn::make('tenant_count')
                    ->label('Tenants')
                    ->sortable(),
                TextColumn::make('recovery_support_access')
                    ->label('Recovery support')
                    ->badge()
                    ->getStateUsing(fn (Workspace $record): string => app(SupportAccessGrantResolver::class)->activeRecoveryGrantFor($record) instanceof SupportAccessGrant
                        ? 'Active'
                        : 'Missing')
                    ->color(fn (string $state): string => $state === 'Active' ? 'success' : 'warning'),
                TextColumn::make('updated_at')
                    ->label('Last activity')
                    ->since()
                    ->sortable(),
            ])
            ->emptyStateHeading('No workspaces')
            ->emptyStateDescription('No workspaces exist in the system yet.')
            ->bulkActions([]);
    }

    /**
     * @return array<array{action: string, actor: string|null, workspace: string|null, recorded_at: string}>
     */
    public function getRecentBreakGlassActions(): array
    {
        return $this->getRecentRecoveryGovernanceActions();
    }

    /**
     * @return array<array{action: string, actor: string|null, workspace: string|null, recorded_at: string}>
     */
    public function getRecentRecoveryGovernanceActions(): array
    {
        return AuditLog::query()
            ->where(function (Builder $query): void {
                $query
                    ->where('action', 'like', '%break_glass%')
                    ->orWhere('action', 'like', 'support_access.%');
            })
            ->orderByDesc('recorded_at')
            ->limit(10)
            ->get()
            ->map(fn (AuditLog $log): array => [
                'action' => (string) $log->action,
                'actor' => $log->actor_email ?: 'Unknown',
                'workspace' => $log->metadata['metadata']['workspace_id'] ?? null
                    ? Workspace::query()->whereKey((int) $log->metadata['metadata']['workspace_id'])->value('name')
                    : null,
                'recorded_at' => $log->recorded_at?->diffForHumans() ?? 'Unknown',
            ])
            ->all();
    }

    /**
     * @return array<Action>
     */
    protected function getHeaderActions(): array
    {
        $breakGlass = app(BreakGlassSession::class);

        return [
            Action::make('assign_owner')
                ->label('Emergency: Assign Owner')
                ->icon('heroicon-o-shield-exclamation')
                ->color('danger')
                ->requiresConfirmation()
                ->modalHeading('Assign workspace owner')
                ->modalDescription('This is a recovery action. It requires active break-glass mode and an active workspace recovery support-access grant for the selected workspace.')
                ->form([
                    Select::make('workspace_id')
                        ->label('Workspace')
                        ->required()
                        ->searchable()
                        ->getSearchResultsUsing(function (string $search): array {
                            return Workspace::query()
                                ->where('name', 'like', "%{$search}%")
                                ->orderBy('name')
                                ->limit(25)
                                ->pluck('name', 'id')
                                ->all();
                        })
                        ->getOptionLabelUsing(function ($value): ?string {
                            if (! is_numeric($value)) {
                                return null;
                            }

                            return Workspace::query()->whereKey((int) $value)->value('name');
                        }),

                    Select::make('target_user_id')
                        ->label('User')
                        ->required()
                        ->searchable()
                        ->getSearchResultsUsing(function (string $search): array {
                            return User::query()
                                ->where('email', 'like', "%{$search}%")
                                ->orderBy('email')
                                ->limit(25)
                                ->pluck('email', 'id')
                                ->all();
                        })
                        ->getOptionLabelUsing(function ($value): ?string {
                            if (! is_numeric($value)) {
                                return null;
                            }

                            return User::query()->whereKey((int) $value)->value('email');
                        }),

                    Textarea::make('reason')
                        ->label('Reason')
                        ->required()
                        ->minLength(5)
                        ->maxLength(500)
                        ->rows(4),
                ])
                ->action(function (array $data, BreakGlassSession $breakGlass, WorkspaceAuditLogger $auditLogger): void {
                    $platformUser = auth('platform')->user();

                    if (! $platformUser instanceof PlatformUser) {
                        abort(403);
                    }

                    if (! $platformUser->hasCapability(PlatformCapabilities::USE_BREAK_GLASS)) {
                        abort(403);
                    }

                    $workspaceId = (int) ($data['workspace_id'] ?? 0);
                    $targetUserId = (int) ($data['target_user_id'] ?? 0);
                    $reason = (string) ($data['reason'] ?? '');

                    $workspace = Workspace::query()->whereKey($workspaceId)->firstOrFail();
                    $targetUser = User::query()->whereKey($targetUserId)->firstOrFail();
                    $supportAccessResolver = app(SupportAccessGrantResolver::class);
                    $supportGrant = $supportAccessResolver->activeRecoveryGrantFor($workspace);

                    if (! $breakGlass->isActive()) {
                        throw ValidationException::withMessages([
                            'workspace_id' => 'Activate break-glass mode before assigning a workspace owner.',
                        ]);
                    }

                    if (! $supportGrant instanceof SupportAccessGrant) {
                        throw ValidationException::withMessages([
                            'workspace_id' => 'Active workspace recovery support access is required before assigning a workspace owner.',
                        ]);
                    }

                    $membership = WorkspaceMembership::query()->firstOrNew([
                        'workspace_id' => (int) $workspace->getKey(),
                        'user_id' => (int) $targetUser->getKey(),
                    ]);

                    $fromRole = $membership->exists ? (string) $membership->role : null;

                    $membership->forceFill([
                        'role' => WorkspaceRole::Owner->value,
                    ])->save();

                    $auditLogger->log(
                        workspace: $workspace,
                        action: AuditActionId::WorkspaceMembershipBreakGlassAssignOwner->value,
                        context: [
                            'metadata' => [
                                'workspace_id' => (int) $workspace->getKey(),
                                'actor_user_id' => (int) $platformUser->getKey(),
                                'target_user_id' => (int) $targetUser->getKey(),
                                'attempted_role' => WorkspaceRole::Owner->value,
                                'from_role' => $fromRole,
                                'reason' => trim($reason),
                                'source' => 'break_glass',
                                'support_access_grant_id' => (int) $supportGrant->getKey(),
                                'support_access_scope' => (string) $supportGrant->scope,
                                'support_access_expires_at' => $supportGrant->expires_at?->toISOString(),
                            ],
                        ],
                        actor: null,
                        status: 'success',
                        resourceType: 'workspace',
                        resourceId: (string) $workspace->getKey(),
                        actorId: (int) $platformUser->getKey(),
                        actorEmail: $platformUser->email,
                        actorName: $platformUser->name,
                    );

                    Notification::make()
                        ->title('Owner assigned')
                        ->success()
                        ->send();
                })
                ->disabled(fn (): bool => ! $breakGlass->isActive())
                ->tooltip(fn (): ?string => ! $breakGlass->isActive() ? 'Activate break-glass mode on the Dashboard first. Workspace recovery support access is also required for the selected workspace.' : null),
        ];
    }

    public function recoveryBoundarySummary(): string
    {
        $breakGlass = app(BreakGlassSession::class);

        if (! $breakGlass->isActive()) {
            return 'Blocked: break-glass mode is inactive. Activate break-glass on the system dashboard and confirm the selected workspace has active recovery-scoped support access.';
        }

        return 'Break-glass mode is active. The selected workspace must still have active recovery-scoped support access before owner repair can execute.';
    }
}
