<?php

namespace App\Filament\Resources\PolicyResource\RelationManagers;

use App\Filament\Resources\RestoreRunResource;
use App\Models\PolicyVersion;
use App\Models\Tenant;
use App\Models\User;
use App\Services\Auth\CapabilityResolver;
use App\Services\Intune\RestoreService;
use App\Support\Auth\Capabilities;
use App\Support\Badges\TagBadgeDomain;
use App\Support\Badges\TagBadgeRenderer;
use App\Support\Rbac\UiEnforcement;
use App\Support\Rbac\UiTooltips;
use App\Support\Ui\ActionSurface\ActionSurfaceDeclaration;
use App\Support\Ui\ActionSurface\Enums\ActionSurfaceInspectAffordance;
use App\Support\Ui\ActionSurface\Enums\ActionSurfaceProfile;
use App\Support\Ui\ActionSurface\Enums\ActionSurfaceSlot;
use Filament\Actions;
use Filament\Forms;
use Filament\Notifications\Notification;
use Filament\Resources\RelationManagers\RelationManager;
use Filament\Tables;
use Filament\Tables\Table;

class VersionsRelationManager extends RelationManager
{
    protected static string $relationship = 'versions';

    public static function actionSurfaceDeclaration(): ActionSurfaceDeclaration
    {
        return ActionSurfaceDeclaration::forRelationManager(ActionSurfaceProfile::RelationManager)
            ->exempt(ActionSurfaceSlot::ListHeader, 'Versions sub-list intentionally has no header actions.')
            ->satisfy(ActionSurfaceSlot::InspectAffordance, ActionSurfaceInspectAffordance::ViewAction->value)
            ->exempt(ActionSurfaceSlot::ListRowMoreMenu, 'Only two row actions are present, so no secondary row menu is needed.')
            ->exempt(ActionSurfaceSlot::ListBulkMoreGroup, 'Bulk actions are intentionally omitted for version restore safety.')
            ->exempt(ActionSurfaceSlot::ListEmptyState, 'No inline empty-state action is exposed in this embedded relation manager.');
    }

    public function table(Table $table): Table
    {
        $restoreToIntune = Actions\Action::make('restore_to_intune')
            ->label('Restore to Intune')
            ->icon('heroicon-o-arrow-path-rounded-square')
            ->color('danger')
            ->requiresConfirmation()
            ->modalHeading(fn (PolicyVersion $record): string => "Restore version {$record->version_number} to Intune?")
            ->modalSubheading('Creates a restore run using this policy version snapshot.')
            ->form([
                Forms\Components\Toggle::make('is_dry_run')
                    ->label('Preview only (dry-run)')
                    ->default(true),
            ])
            ->action(function (PolicyVersion $record, array $data, RestoreService $restoreService) {
                $tenant = Tenant::current();
                $user = auth()->user();

                if (! $tenant instanceof Tenant || ! $user instanceof User) {
                    Notification::make()
                        ->title('Missing tenant or user context.')
                        ->danger()
                        ->send();

                    return;
                }

                if ($record->tenant_id !== $tenant->id) {
                    Notification::make()
                        ->title('Policy version belongs to a different tenant')
                        ->danger()
                        ->send();

                    return;
                }

                try {
                    $run = $restoreService->executeFromPolicyVersion(
                        tenant: $tenant,
                        version: $record,
                        dryRun: (bool) ($data['is_dry_run'] ?? true),
                        actorEmail: $user->email,
                        actorName: $user->name,
                    );
                } catch (\Throwable $throwable) {
                    Notification::make()
                        ->title('Restore run failed to start')
                        ->body($throwable->getMessage())
                        ->danger()
                        ->send();

                    return;
                }

                Notification::make()
                    ->title('Restore run started')
                    ->success()
                    ->send();

                return redirect(RestoreRunResource::getUrl('view', ['record' => $run]));
            });

        UiEnforcement::forAction($restoreToIntune)
            ->requireCapability(Capabilities::TENANT_MANAGE)
            ->apply();

        $restoreToIntune
            ->disabled(function (PolicyVersion $record): bool {
                if (($record->metadata['source'] ?? null) === 'metadata_only') {
                    return true;
                }

                $tenant = Tenant::current();
                $user = auth()->user();

                if (! $tenant instanceof Tenant || ! $user instanceof User) {
                    return true;
                }

                $resolver = app(CapabilityResolver::class);

                if (! $resolver->isMember($user, $tenant)) {
                    return true;
                }

                return ! $resolver->can($user, $tenant, Capabilities::TENANT_MANAGE);
            })
            ->tooltip(function (PolicyVersion $record): ?string {
                if (($record->metadata['source'] ?? null) === 'metadata_only') {
                    return 'Disabled for metadata-only snapshots (Graph did not provide policy settings).';
                }

                $tenant = Tenant::current();
                $user = auth()->user();

                if (! $tenant instanceof Tenant || ! $user instanceof User) {
                    return null;
                }

                $resolver = app(CapabilityResolver::class);

                if (! $resolver->isMember($user, $tenant)) {
                    return null;
                }

                if (! $resolver->can($user, $tenant, Capabilities::TENANT_MANAGE)) {
                    return UiTooltips::INSUFFICIENT_PERMISSION;
                }

                return null;
            });

        return $table
            ->columns([
                Tables\Columns\TextColumn::make('version_number')->sortable(),
                Tables\Columns\TextColumn::make('captured_at')->dateTime()->sortable(),
                Tables\Columns\TextColumn::make('created_by')->label('Actor'),
                Tables\Columns\TextColumn::make('policy_type')
                    ->badge()
                    ->formatStateUsing(TagBadgeRenderer::label(TagBadgeDomain::PolicyType))
                    ->color(TagBadgeRenderer::color(TagBadgeDomain::PolicyType))
                    ->toggleable(isToggledHiddenByDefault: true),
            ])
            ->defaultSort('version_number', 'desc')
            ->paginated(\App\Support\Filament\TablePaginationProfiles::relationManager())
            ->filters([])
            ->headerActions([])
            ->actions([
                $restoreToIntune,
                Actions\ViewAction::make()
                    ->url(fn ($record) => \App\Filament\Resources\PolicyVersionResource::getUrl('view', ['record' => $record]))
                    ->openUrlInNewTab(false),
            ])
            ->bulkActions([])
            ->emptyStateHeading('No versions captured')
            ->emptyStateDescription('Capture or sync this policy again to create version history entries.');
    }
}
