<?php

namespace App\Filament\Resources;

use App\enum\UserLevel;
use App\Filament\Resources\UserResource\Pages\CreateUser;
use App\Filament\Resources\UserResource\Pages\EditUser;
use App\Filament\Resources\UserResource\Pages\ListUsers;
use App\Filament\Resources\UserResource\RelationManagers\LogsRelationManager;
use App\Filament\Resources\UserResource\RelationManagers\UsageLogsRelationManager;
use App\Models\User;
use App\Services\ImpersonationService;
use BackedEnum;
use Filament\Actions\Action;
use Filament\Actions\BulkAction;
use Filament\Actions\BulkActionGroup;
use Filament\Actions\DeleteBulkAction;
use Filament\Actions\EditAction;
use Filament\Forms\Components\DatePicker;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
use Filament\Notifications\Notification;
use Filament\Resources\Resource;
use Filament\Schemas\Schema;
use Filament\Tables\Columns\IconColumn;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Filters\SelectFilter;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use UnitEnum;

class UserResource extends Resource
{
    protected static ?string $model = User::class;

    protected static string|BackedEnum|null $navigationIcon = 'heroicon-o-users';

    protected static string|UnitEnum|null $navigationGroup = 'Admin';

    public static function form(Schema $schema): Schema
    {
        return $schema
            ->components([
                TextInput::make('name')
                    ->required()
                    ->maxLength(255),

                TextInput::make('email')
                    ->email()
                    ->required()
                    ->maxLength(255),
                TextInput::make('password')
                    ->password()
                    ->required()
                    ->minLength(6)
                    ->maxLength(255)
                    ->visibleOn('create'),
                TextInput::make('email_verified_at')
                    ->label('Email Verification Status')
                    ->disabled()
                    ->formatStateUsing(fn ($record): string => $record->email_verified_at ?? ''
                        ? 'Verified at '.$record->email_verified_at->toDateTimeString()
                        : 'Not Verified')
                    ->helperText('Shows whether the user has verified their email address.'),
                TextInput::make('stripe_id')
                    ->label('Stripe ID')
                    ->disabled()
                    ->helperText('Automatically managed by Stripe'),

                TextInput::make('pm_type')
                    ->label('Payment Method Type')
                    ->disabled(),

                TextInput::make('pm_last_four')
                    ->label('Card Last 4 Digits')
                    ->disabled(),

                DatePicker::make('trial_ends_at')
                    ->label('Trial Ends At')
                    ->disabled()
                    ->displayFormat('Y-m-d H:i:s'),
                Select::make('level')
                    ->label('User Level')
                    ->options(UserLevel::class)
                    ->enum(UserLevel::class)
                    ->required()
                    ->helperText('Select the appropriate user level. Super Admin has full system access.'),

            ]);
    }

    public static function table(Table $table): Table
    {
        return $table
            ->columns([
                TextColumn::make('name')->sortable()->searchable(),
                TextColumn::make('email')->sortable()->searchable(),
                IconColumn::make('email_verified_at')
                    ->label('Verified')
                    ->boolean()
                    ->trueIcon('heroicon-o-check-circle')
                    ->falseIcon('heroicon-o-x-circle')
                    ->trueColor('success')
                    ->falseColor('danger')
                    ->getStateUsing(fn ($record): bool => ! is_null($record->email_verified_at))
                    ->sortable(),
                TextColumn::make('level')
                    ->label('User Level')
                    ->badge()
                    ->getStateUsing(fn ($record): string => $record->level->getLabel())
                    ->color(fn ($record): string => $record->level->getColor())
                    ->icon(fn ($record): string => $record->level->getIcon())
                    ->sortable(),
                TextColumn::make('stripe_id')->label('Stripe ID')->copyable(),
                TextColumn::make('pm_last_four')->label('Card Last 4'),
                TextColumn::make('trial_ends_at')->label('Trial Ends')->dateTime()->sortable(),
            ])
            ->defaultSort('created_at', 'desc')
            ->filters([
                SelectFilter::make('level')
                    ->label('User Level')
                    ->options(UserLevel::class),
                SelectFilter::make('subscription_status')
                    ->label('Subscription Status')
                    ->options([
                        'subscribed' => 'Has Active Subscription',
                        'not_subscribed' => 'No Active Subscription',
                    ])
                    ->query(function ($query, array $data): void {
                        if ($data['value'] === 'subscribed') {
                            $query->whereHas('subscriptions', function ($query): void {
                                $query->where('stripe_status', 'active')
                                    ->orWhere('stripe_status', 'trialing');
                            });
                        } elseif ($data['value'] === 'not_subscribed') {
                            $query->whereDoesntHave('subscriptions', function ($query): void {
                                $query->where('stripe_status', 'active')
                                    ->orWhere('stripe_status', 'trialing');
                            });
                        }
                    }),
                SelectFilter::make('email_verified')
                    ->label('Email Verification')
                    ->options([
                        'verified' => 'Verified',
                        'not_verified' => 'Not Verified',
                    ])
                    ->query(function ($query, array $data): void {
                        if ($data['value'] === 'verified') {
                            $query->whereNotNull('email_verified_at');
                        } elseif ($data['value'] === 'not_verified') {
                            $query->whereNull('email_verified_at');
                        }
                    }),
            ])
            ->recordActions([
                EditAction::make(),
                Action::make('impersonate')
                    ->label('Login as User')
                    ->icon('heroicon-o-arrow-right-on-rectangle')
                    ->color('warning')
                    ->requiresConfirmation()
                    ->modalHeading('Start User Impersonation')
                    ->modalDescription('This will open a new tab where you will be logged in as this user. All actions will be logged for security. Your admin panel will remain open in this tab.')
                    ->modalSubmitActionLabel('Start Impersonation')
                    ->modalCancelActionLabel('Cancel')
                    ->visible(fn (User $record): bool => auth()->user()?->isSuperAdmin() &&
                        $record->isNormalUser() &&
                        ! app(ImpersonationService::class)->isImpersonating()
                    )
                    ->url(function (User $record): string {
                        $admin = auth()->user();
                        $impersonationService = app(ImpersonationService::class);

                        if (! $impersonationService->canImpersonate($admin, $record)) {
                            Notification::make()
                                ->title('Impersonation Failed')
                                ->body('Unable to start impersonation. Please check permissions and try again.')
                                ->danger()
                                ->send();

                            return '#';
                        }

                        // Return impersonation URL
                        return route('impersonation.start', $record);
                    })
                    ->openUrlInNewTab(),
            ])
            ->toolbarActions([
                Action::make('stopImpersonation')
                    ->label('Stop Impersonating')
                    ->icon('heroicon-o-arrow-left-on-rectangle')
                    ->color('danger')
                    ->visible(fn (): bool => app(ImpersonationService::class)->isImpersonating())
                    ->action(function () {
                        $impersonationService = app(ImpersonationService::class);

                        if (! $impersonationService->stopImpersonation(request())) {
                            Notification::make()
                                ->title('Failed to Stop Impersonation')
                                ->body('Unable to stop impersonation session.')
                                ->danger()
                                ->send();

                            return;
                        }

                        Notification::make()
                            ->title('Impersonation Ended')
                            ->body('You have been returned to your admin account.')
                            ->success()
                            ->send();

                        return redirect()->to(\Filament\Pages\Dashboard::getUrl());
                    }),
                BulkActionGroup::make([
                    DeleteBulkAction::make(),
                    BulkAction::make('updateLevel')
                        ->label('Update User Level')
                        ->action(function (Collection $records, array $data): void {
                            $newLevel = (int) $data['new_level'];

                            // Prevent bulk updating to Super Admin level for security
                            if ($newLevel === UserLevel::SUPERADMIN->value) {
                                $message = 'Cannot bulk assign Super Admin level for security reasons.';

                                Log::warning('Attempted bulk Super Admin assignment', [
                                    'user_ids' => $records->pluck('id')->toArray(),
                                    'attempted_level' => $newLevel,
                                    'ip' => request()->ip(),
                                ]);

                                Notification::make()
                                    ->title('Security Restriction')
                                    ->body($message)
                                    ->danger()
                                    ->send();

                                return;
                            }

                            DB::table('users')
                                ->whereIn('id', $records->pluck('id'))
                                ->update(['level' => $newLevel]);

                            Log::info('Bulk user level update completed', [
                                'user_ids' => $records->pluck('id')->toArray(),
                                'new_level' => $newLevel,
                                'updated_by' => auth()->id(),
                            ]);

                            Notification::make()
                                ->title('User Level Updated')
                                ->body('The selected users\' levels have been updated successfully.')
                                ->success()
                                ->send();
                        })
                        ->icon('heroicon-o-pencil')
                        ->color('primary')
                        ->modalHeading('Select User Level')
                        ->modalDescription('Please choose the user level to apply to the selected users.')
                        ->modalSubmitActionLabel('Update Level')
                        ->modalCancelActionLabel('Cancel')
                        ->form([
                            Select::make('new_level')
                                ->label('Select User Level')
                                ->options([
                                    UserLevel::NORMALUSER->value => UserLevel::NORMALUSER->getLabel(),
                                    UserLevel::BANNEDUSER->value => UserLevel::BANNEDUSER->getLabel(),
                                ])
                                ->required()
                                ->helperText('Super Admin level cannot be assigned via bulk action for security.'),
                        ]),
                ]),
            ]);
    }

    public static function getRelations(): array
    {
        return [
            LogsRelationManager::class,
            UsageLogsRelationManager::class,
        ];
    }

    public static function getPages(): array
    {
        return [
            'index' => ListUsers::route('/'),
            'create' => CreateUser::route('/create'),
            'edit' => EditUser::route('/{record}/edit'),
        ];
    }
}
