<?php

declare(strict_types=1);

/**
 * 本文件属于 DBErp 进销存系统。
 *
 * 版权所有 © 2026 北京珑大钜商科技有限公司。保留所有权利。
 *
 * 未经官方授权，不得删除、篡改或隐藏本文件中的版权声明、产品标识与来源信息。
 * 商业授权、官方更新与技术支持服务，请以珑大官方支持中心记录为准。
 *
 * @link https://support.loongdom.cn
 * @see  https://www.dberp.com.cn
 */

namespace App\Filament\HostPluginCenter\Widgets;

use App\Models\HostPluginOperationLog;
use App\Models\User;
use App\Services\Plugin\HostPluginOperationLogPruningService;
use App\Support\DberpSystemProfileSettings;
use App\Support\HostPluginCenterDisplay;
use Carbon\CarbonInterface;
use Filament\Actions\Action;
use Filament\Notifications\Notification;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Enums\PaginationMode;
use Filament\Tables\Filters\SelectFilter;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Str;
use Livewire\Attributes\On;

final class ActivityLogTableWidget extends HostPluginCenterTableWidget
{
    #[On('plugin-center-data-changed')]
    public function refreshActivityLogTable(): void
    {
        $this->resetTable();
    }

    public function table(Table $table): Table
    {
        $display = app(HostPluginCenterDisplay::class);

        return $table
            ->heading(null)
            ->queryStringIdentifier('hostPluginActivity')
            ->query($display->activityQuery())
            ->defaultSort('created_at', 'desc')
            ->paginationMode(PaginationMode::Default)
            ->paginated([20, 50, 100])
            ->defaultPaginationPageOption(20)
            ->emptyStateHeading(__('dberp.empty_states.default_empty'))
            ->emptyStateDescription($display->activityEmptyMessage())
            ->emptyStateIcon('heroicon-o-clipboard-document-list')
            ->headerActions([
                Action::make('pruneExpiredActivity')
                    ->label(__('dberp.plugin_center.activity.prune.action'))
                    ->icon('heroicon-o-trash')
                    ->color('danger')
                    ->requiresConfirmation()
                    ->modalIcon('heroicon-o-trash')
                    ->modalIconColor('danger')
                    ->modalHeading(__('dberp.plugin_center.activity.prune.heading'))
                    ->modalDescription(fn (): string => (string) __('dberp.plugin_center.activity.prune.description', [
                        'days' => $this->retentionDays(),
                        'count' => app(HostPluginOperationLogPruningService::class)->countOlderThan($this->retentionDays()),
                    ]))
                    ->visible(fn (): bool => $this->canPruneExpiredActivity())
                    ->authorize(fn (): bool => $this->canPruneExpiredActivity())
                    ->disabled(fn (): bool => app(HostPluginOperationLogPruningService::class)
                        ->countOlderThan($this->retentionDays()) === 0)
                    ->tooltip(fn (): ?string => app(HostPluginOperationLogPruningService::class)
                        ->countOlderThan($this->retentionDays()) === 0
                            ? (string) __('dberp.plugin_center.activity.prune.nothing_tooltip', [
                                'days' => $this->retentionDays(),
                            ])
                            : null)
                    ->action(function (HostPluginOperationLogPruningService $pruning): void {
                        $days = $this->retentionDays();
                        $deleted = $pruning->deleteOlderThan($days);

                        Notification::make()
                            ->title(__('dberp.plugin_center.activity.prune.completed_title'))
                            ->body((string) __('dberp.plugin_center.activity.prune.completed_body', [
                                'count' => $deleted,
                                'days' => $days,
                            ]))
                            ->success()
                            ->send();

                        $this->resetTable();
                        $this->dispatch('plugin-center-data-changed');
                    }),
            ])
            ->columns([
                TextColumn::make('created_at')
                    ->label(__('dberp.plugin_center.activity.columns.time'))
                    ->formatStateUsing(fn (?CarbonInterface $state): ?string => $state
                        ?->timezone(DberpSystemProfileSettings::displayTimezone())
                        ->format('Y-m-d H:i:s'))
                    ->sortable(),
                TextColumn::make('plugin_code')
                    ->label(__('dberp.plugin_center.activity.columns.plugin'))
                    ->formatStateUsing(fn (?string $state): ?string => $display->activityPluginLabel($state))
                    ->searchable(query: function (Builder $query, string $search) use ($display): Builder {
                        $matchingCodes = collect($display->activityPluginOptions())
                            ->filter(fn (string $label): bool => Str::contains(
                                Str::lower($label),
                                Str::lower($search),
                            ))
                            ->keys()
                            ->all();

                        return $query->where(function (Builder $query) use ($matchingCodes, $search): void {
                            $query->where('plugin_code', 'like', '%'.$search.'%');

                            if ($matchingCodes !== []) {
                                $query->orWhereIn('plugin_code', $matchingCodes);
                            }
                        });
                    })
                    ->placeholder('—'),
                TextColumn::make('operation')
                    ->label(__('dberp.plugin_center.activity.columns.operation'))
                    ->formatStateUsing(fn (?string $state): string => $display->activityOperationLabel((string) $state))
                    ->searchable(query: function (Builder $query, string $search) use ($display): Builder {
                        $matchingOperations = collect($display->activityOperationOptions())
                            ->filter(fn (string $label): bool => Str::contains(
                                Str::lower($label),
                                Str::lower($search),
                            ))
                            ->keys()
                            ->all();

                        return $query->where(function (Builder $query) use ($matchingOperations, $search): void {
                            $query->where('operation', 'like', '%'.$search.'%');

                            if ($matchingOperations !== []) {
                                $query->orWhereIn('operation', $matchingOperations);
                            }
                        });
                    }),
                TextColumn::make('result_status')
                    ->label(__('dberp.plugin_center.activity.columns.result'))
                    ->formatStateUsing(fn (?string $state): string => $display->activityResultLabel((string) $state))
                    ->badge()
                    ->color(fn (HostPluginOperationLog $record): string => $display->activityResultColor($record->result_status)),
                TextColumn::make('message')
                    ->label(__('dberp.plugin_center.activity.columns.message'))
                    ->placeholder('—')
                    ->searchable()
                    ->copyable()
                    ->copyMessage(__('dberp.plugin_center.activity.message_copied'))
                    ->wrap(),
            ])
            ->filters([
                SelectFilter::make('result_status')
                    ->label(__('dberp.plugin_center.activity.columns.result'))
                    ->options([
                        'failed' => __('dberp.plugin_center.activity.results.failed'),
                        'completed' => __('dberp.plugin_center.activity.results.completed'),
                    ]),
                SelectFilter::make('operation')
                    ->label(__('dberp.plugin_center.activity.columns.operation'))
                    ->options(fn (): array => $display->activityOperationOptions()),
                SelectFilter::make('plugin_code')
                    ->label(__('dberp.plugin_center.activity.columns.plugin'))
                    ->options(fn (): array => $display->activityPluginOptions()),
            ])
            ->recordClasses(fn (HostPluginOperationLog $record): ?string => $record->result_status === 'failed'
                ? 'fi-color-danger'
                : null);
    }

    private function retentionDays(): int
    {
        return max(1, (int) config('dberp.plugin_center.operation_log_retention_days', 90));
    }

    private function canPruneExpiredActivity(): bool
    {
        $user = Auth::user();

        return $user instanceof User && $user->isSuperAdmin();
    }
}
