user()->can(Permission::ACTION_SCHEDULE_READ, Filament::getTenant());
    }
    public static function canCreate(): bool
    {
        return auth()->user()->can(Permission::ACTION_SCHEDULE_CREATE, Filament::getTenant());
    }
    public static function canEdit(Model $record): bool
    {
        return auth()->user()->can(Permission::ACTION_SCHEDULE_UPDATE, Filament::getTenant());
    }
    public static function canDelete(Model $record): bool
    {
        return auth()->user()->can(Permission::ACTION_SCHEDULE_DELETE, Filament::getTenant());
    }
    /**
     * @throws Exception
     */
    public static function defaultForm(Schema $schema): Schema
    {
        return $schema
            ->columns([
                'default' => 1,
                'lg' => 2,
            ])
            ->components([
                TextInput::make('name')
                    ->label(trans('server/schedule.name'))
                    ->columnSpanFull()
                    ->autocomplete(false)
                    ->columnSpanFull()
                    ->required(),
                Toggle::make('only_when_online')
                    ->label(trans('server/schedule.only_online'))
                    ->hintIcon('tabler-question-mark', trans('server/schedule.only_online_hint'))
                    ->inline(false)
                    ->required()
                    ->default(1),
                Toggle::make('is_active')
                    ->label(trans('server/schedule.enabled'))
                    ->hintIcon('tabler-question-mark', trans('server/schedule.enabled_hint'))
                    ->inline(false)
                    ->hiddenOn('view')
                    ->required()
                    ->default(1),
                ToggleButtons::make('status')
                    ->enum(ScheduleStatus::class)
                    ->formatStateUsing(fn (?Schedule $schedule) => $schedule?->status->value ?? 'new')
                    ->options(fn (?Schedule $schedule) => [$schedule?->status->value ?? 'new' => $schedule?->status->getLabel() ?? 'New'])
                    ->visibleOn('view'),
                Section::make('Cron')
                    ->label(trans('server/schedule.cron'))
                    ->description(function (Get $get) {
                        try {
                            $nextRun = Utilities::getScheduleNextRunDate($get('cron_minute'), $get('cron_hour'), $get('cron_day_of_month'), $get('cron_month'), $get('cron_day_of_week'))->timezone(auth()->user()->timezone);
                        } catch (Exception) {
                            $nextRun = trans('server/schedule.invalid');
                        }
                        return new HtmlString(trans('server/schedule.cron_body') . '
' . trans('server/schedule.cron_timezone', ['timezone' => auth()->user()->timezone, 'next_run' => $nextRun]));
                    })
                    ->schema([
                        Actions::make([
                            CronPresetAction::make('hourly')
                                ->label(trans('server/schedule.time.hourly'))
                                ->cron('0', '*', '*', '*', '*'),
                            CronPresetAction::make('daily')
                                ->label(trans('server/schedule.time.daily'))
                                ->cron('0', '0', '*', '*', '*'),
                            CronPresetAction::make('weekly_monday')
                                ->label(trans('server/schedule.time.weekly_mon'))
                                ->cron('0', '0', '*', '*', '1'),
                            CronPresetAction::make('weekly_sunday')
                                ->label(trans('server/schedule.time.weekly_sun'))
                                ->cron('0', '0', '*', '*', '0'),
                            CronPresetAction::make('monthly')
                                ->label(trans('server/schedule.time.monthly'))
                                ->cron('0', '0', '1', '*', '*'),
                            CronPresetAction::make('every_x_minutes')
                                ->label(trans('server/schedule.time.every_min'))
                                ->color(fn (Get $get) => str($get('cron_minute'))->startsWith('*/')
                                                    && $get('cron_hour') == '*'
                                                    && $get('cron_day_of_month') == '*'
                                                    && $get('cron_month') == '*'
                                                    && $get('cron_day_of_week') == '*' ? 'success' : 'primary')
                                ->schema([
                                    TextInput::make('x')
                                        ->hiddenLabel()
                                        ->numeric()
                                        ->minValue(1)
                                        ->maxValue(60)
                                        ->prefix(trans('server/schedule.time.every'))
                                        ->suffix(trans('server/schedule.time.minutes')),
                                ])
                                ->action(function (Set $set, $data) {
                                    $set('cron_minute', '*/' . $data['x']);
                                    $set('cron_hour', '*');
                                    $set('cron_day_of_month', '*');
                                    $set('cron_month', '*');
                                    $set('cron_day_of_week', '*');
                                }),
                            CronPresetAction::make('every_x_hours')
                                ->color(fn (Get $get) => $get('cron_minute') == '0'
                                                    && str($get('cron_hour'))->startsWith('*/')
                                                    && $get('cron_day_of_month') == '*'
                                                    && $get('cron_month') == '*'
                                                    && $get('cron_day_of_week') == '*' ? 'success' : 'primary')
                                ->schema([
                                    TextInput::make('x')
                                        ->hiddenLabel()
                                        ->numeric()
                                        ->minValue(1)
                                        ->maxValue(24)
                                        ->prefix(trans('server/schedule.time.every'))
                                        ->suffix(trans('server/schedule.time.hours')),
                                ])
                                ->action(function (Set $set, $data) {
                                    $set('cron_minute', '0');
                                    $set('cron_hour', '*/' . $data['x']);
                                    $set('cron_day_of_month', '*');
                                    $set('cron_month', '*');
                                    $set('cron_day_of_week', '*');
                                }),
                            CronPresetAction::make('every_x_days')
                                ->color(fn (Get $get) => $get('cron_minute') == '0'
                                                    && $get('cron_hour') == '0'
                                                    && str($get('cron_day_of_month'))->startsWith('*/')
                                                    && $get('cron_month') == '*'
                                                    && $get('cron_day_of_week') == '*' ? 'success' : 'primary')
                                ->schema([
                                    TextInput::make('x')
                                        ->hiddenLabel()
                                        ->numeric()
                                        ->minValue(1)
                                        ->maxValue(24)
                                        ->prefix(trans('server/schedule.time.every'))
                                        ->suffix(trans('server/schedule.time.days')),
                                ])
                                ->action(function (Set $set, $data) {
                                    $set('cron_minute', '0');
                                    $set('cron_hour', '0');
                                    $set('cron_day_of_month', '*/' . $data['x']);
                                    $set('cron_month', '*');
                                    $set('cron_day_of_week', '*');
                                }),
                            CronPresetAction::make('every_x_months')
                                ->color(fn (Get $get) => $get('cron_minute') == '0'
                                                    && $get('cron_hour') == '0'
                                                    && $get('cron_day_of_month') == '1'
                                                    && str($get('cron_month'))->startsWith('*/')
                                                    && $get('cron_day_of_week') == '*' ? 'success' : 'primary')
                                ->schema([
                                    TextInput::make('x')
                                        ->hiddenLabel()
                                        ->numeric()
                                        ->minValue(1)
                                        ->maxValue(24)
                                        ->prefix(trans('server/schedule.time.every'))
                                        ->suffix(trans('server/schedule.time.months')),
                                ])
                                ->action(function (Set $set, $data) {
                                    $set('cron_minute', '0');
                                    $set('cron_hour', '0');
                                    $set('cron_day_of_month', '1');
                                    $set('cron_month', '*/' . $data['x']);
                                    $set('cron_day_of_week', '*');
                                }),
                            CronPresetAction::make('every_x_day_of_week')
                                ->color(fn (Get $get) => $get('cron_minute') == '0'
                                                    && $get('cron_hour') == '0'
                                                    && $get('cron_day_of_month') == '*'
                                                    && $get('cron_month') == '*'
                                                    && $get('cron_day_of_week') != '*' ? 'success' : 'primary')
                                ->schema([
                                    Select::make('x')
                                        ->hiddenLabel()
                                        ->prefix(trans('server/schedule.time.every'))
                                        ->options([
                                            '1' => trans('server/schedule.time.monday'),
                                            '2' => trans('server/schedule.time.tuesday'),
                                            '3' => trans('server/schedule.time.wednesday'),
                                            '4' => trans('server/schedule.time.thursday'),
                                            '5' => trans('server/schedule.time.friday'),
                                            '6' => trans('server/schedule.time.saturday'),
                                            '0' => trans('server/schedule.time.sunday'),
                                        ])
                                        ->selectablePlaceholder(false)
                                        ->native(false),
                                ])
                                ->action(function (Set $set, $data) {
                                    $set('cron_minute', '0');
                                    $set('cron_hour', '0');
                                    $set('cron_day_of_month', '*');
                                    $set('cron_month', '*');
                                    $set('cron_day_of_week', $data['x']);
                                }),
                        ])
                            ->hiddenOn('view'),
                        Group::make([
                            TextInput::make('cron_minute')
                                ->label(trans('server/schedule.time.minute'))
                                ->columnSpan([
                                    'default' => 2,
                                    'lg' => 1,
                                ])
                                ->default('*/5')
                                ->required()
                                ->live(),
                            TextInput::make('cron_hour')
                                ->label(trans('server/schedule.time.hour'))
                                ->columnSpan([
                                    'default' => 2,
                                    'lg' => 1,
                                ])
                                ->default('*')
                                ->required()
                                ->live(),
                            TextInput::make('cron_day_of_month')
                                ->label(trans('server/schedule.time.day_of_month'))
                                ->columnSpan([
                                    'default' => 2,
                                    'lg' => 1,
                                ])
                                ->default('*')
                                ->required()
                                ->live(),
                            TextInput::make('cron_month')
                                ->label(trans('server/schedule.time.month'))
                                ->columnSpan([
                                    'default' => 2,
                                    'lg' => 1,
                                ])
                                ->default('*')
                                ->required()
                                ->live(),
                            TextInput::make('cron_day_of_week')
                                ->label(trans('server/schedule.time.day_of_week'))
                                ->columnSpan([
                                    'default' => 2,
                                    'lg' => 1,
                                ])
                                ->default('*')
                                ->required()
                                ->live(),
                        ])
                            ->columns([
                                'default' => 4,
                                'lg' => 5,
                            ]),
                    ])
                    ->columnSpanFull(),
            ]);
    }
    /**
     * @throws Throwable
     */
    public static function defaultTable(Table $table): Table
    {
        return $table
            ->columns([
                TextColumn::make('name')
                    ->label(trans('server/schedule.name'))
                    ->searchable(),
                TextColumn::make('cron')
                    ->label(trans('server/schedule.cron'))
                    ->state(fn (Schedule $schedule) => $schedule->cron_minute . ' ' . $schedule->cron_hour . ' ' . $schedule->cron_day_of_month . ' ' . $schedule->cron_month . ' ' . $schedule->cron_day_of_week),
                TextColumn::make('status')
                    ->label(trans('server/schedule.status'))
                    ->state(fn (Schedule $schedule) => $schedule->status->getLabel())
                    ->color(fn (Schedule $schedule) => $schedule->status->getColor())
                    ->badge(),
                IconColumn::make('only_when_online')
                    ->label(trans('server/schedule.online_only'))
                    ->boolean()
                    ->sortable(),
                DateTimeColumn::make('last_run_at')
                    ->label(trans('server/schedule.last_run'))
                    ->placeholder(trans('server/schedule.never'))
                    ->since()
                    ->sortable(),
                DateTimeColumn::make('next_run_at')
                    ->label(trans('server/schedule.next_run'))
                    ->placeholder(trans('server/schedule.never'))
                    ->since()
                    ->sortable()
                    ->state(fn (Schedule $schedule) => $schedule->status === ScheduleStatus::Active ? $schedule->next_run_at : null),
            ])
            ->recordActions([
                ViewAction::make(),
                EditAction::make(),
                DeleteAction::make()
                    ->after(function (Schedule $schedule) {
                        Activity::event('server:schedule.delete')
                            ->subject($schedule)
                            ->property('name', $schedule->name)
                            ->log();
                    }),
            ])
            ->toolbarActions([
                CreateAction::make()
                    ->hiddenLabel()->iconButton()->iconSize(IconSize::ExtraLarge)
                    ->icon('tabler-calendar-plus')
                    ->color('primary')
                    ->tooltip(trans('server/schedule.new')),
                ImportScheduleAction::make()
                    ->hiddenLabel()->iconButton()->iconSize(IconSize::ExtraLarge)
                    ->icon('tabler-file-import')
                    ->color('success')
                    ->tooltip(trans('server/schedule.import')),
            ]);
    }
    /** @return class-string[] */
    public static function getDefaultRelations(): array
    {
        return [
            TasksRelationManager::class,
        ];
    }
    /** @return array */
    public static function getDefaultPages(): array
    {
        return [
            'index' => ListSchedules::route('/'),
            'create' => CreateSchedule::route('/create'),
            'view' => ViewSchedule::route('/{record}'),
            'edit' => EditSchedule::route('/{record}/edit'),
        ];
    }
    public static function getNextRun(string $minute, string $hour, string $dayOfMonth, string $month, string $dayOfWeek): Carbon
    {
        try {
            return Utilities::getScheduleNextRunDate($minute, $hour, $dayOfMonth, $month, $dayOfWeek);
        } catch (Exception) {
            Notification::make()
                ->title(trans('server/schedule.notification_invalid_cron'))
                ->danger()
                ->send();
            throw new Halt();
        }
    }
    public static function getNavigationLabel(): string
    {
        return trans('server/schedule.title');
    }
}