<?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\Filament\HostPluginCenter\Concerns\InteractsWithHostPluginOperations;
use App\Support\HostPluginCenterDisplay;
use App\Support\HostPluginCenterSettingsPanelFormatter;
use App\Support\HostPluginCenterUsageGuidanceFormatter;
use Filament\Actions\Action;
use Filament\Actions\ActionGroup;
use Filament\Support\Enums\Width;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Filters\SelectFilter;
use Filament\Tables\Table;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Str;
use Livewire\Attributes\On;

final class InstalledPluginsTableWidget extends HostPluginCenterTableWidget
{
    use InteractsWithHostPluginOperations;

    public bool $pluginUpdateInProgress = false;

    public ?string $updatingPluginCode = null;

    #[On('plugin-center-data-changed')]
    public function refreshInstalledPluginsTable(): void
    {
        app(HostPluginCenterDisplay::class)->clearCatalogCache();
        $this->resetTable();
    }

    public function table(Table $table): Table
    {
        $display = app(HostPluginCenterDisplay::class);
        $guidanceFormatter = app(HostPluginCenterUsageGuidanceFormatter::class);
        $settingsPanelFormatter = app(HostPluginCenterSettingsPanelFormatter::class);

        return $table
            ->heading(null)
            ->queryStringIdentifier('hostPluginInstalled')
            ->paginated(false)
            ->records(fn (?string $search, array $filters): array => $this->installedPluginRecords($search, $filters))
            ->emptyStateHeading(__('dberp.empty_states.default_empty'))
            ->emptyStateDescription($display->installedPluginsEmptyMessage())
            ->emptyStateIcon('heroicon-o-inbox')
            ->emptyStateActions([
                Action::make('browseCatalog')
                    ->label(__('dberp.plugin_center.actions.browse_catalog'))
                    ->icon('heroicon-o-squares-plus')
                    ->action(fn () => $this->dispatch('plugin-center-show-catalog')),
            ])
            ->columns([
                TextColumn::make('name')
                    ->label(__('dberp.plugin_center.installed.columns.name'))
                    ->searchable()
                    ->description(fn (array $record): string => $guidanceFormatter->summaryForTableRow($record))
                    ->wrap()
                    ->grow(),
                TextColumn::make('status_label')
                    ->label(__('dberp.plugin_center.installed.columns.status'))
                    ->badge()
                    ->color(fn (array $record): string => (string) ($record['status_color'] ?? 'gray'))
                    ->description(fn (array $record): ?string => filled($record['last_error'] ?? null)
                        ? (string) $record['last_error']
                        : null),
                TextColumn::make('version')
                    ->label(__('dberp.plugin_center.installed.columns.version'))
                    ->description(function (array $record): ?string {
                        if (filled($record['latest_version'] ?? null) && ($record['show_update_action'] ?? false)) {
                            return (string) __('dberp.plugin_center.update.latest_version_label', [
                                'version' => $record['latest_version'],
                            ]);
                        }

                        if (filled($record['update_guidance'] ?? null) && ! ($record['show_update_action'] ?? false)) {
                            return (string) $record['update_guidance'];
                        }

                        return (string) ($record['update_status_label'] ?? '');
                    })
                    ->wrap(),
                TextColumn::make('installed_at_label')
                    ->label(__('dberp.plugin_center.installed.columns.installed_at'))
                    ->placeholder(__('dberp.plugin_center.installed.installed_at_unknown'))
                    ->toggleable(isToggledHiddenByDefault: true),
            ])
            ->filters([
                SelectFilter::make('status')
                    ->label(__('dberp.plugin_center.installed.columns.status'))
                    ->options([
                        'enabled' => __('dberp.plugin_center.status.enabled'),
                        'installed' => __('dberp.plugin_center.status.installed'),
                        'disabled' => __('dberp.plugin_center.status.disabled'),
                        'failed' => __('dberp.plugin_center.status.failed'),
                    ]),
                SelectFilter::make('update_state')
                    ->label(__('dberp.plugin_center.installed.columns.update_status'))
                    ->options([
                        'update_available' => __('dberp.plugin_center.update.state.update_available'),
                        'up_to_date' => __('dberp.plugin_center.update.state.up_to_date'),
                        'check_unavailable' => __('dberp.plugin_center.update.state.check_unavailable'),
                        'license_expired' => __('dberp.plugin_center.update.state.license_expired'),
                    ]),
            ])
            ->recordActions([
                Action::make('enable')
                    ->label(__('dberp.plugin_center.actions.enable'))
                    ->color('success')
                    ->icon('heroicon-o-play-circle')
                    ->requiresConfirmation()
                    ->modalIcon('heroicon-o-play-circle')
                    ->modalHeading(__('dberp.plugin_center.confirm.enable_heading'))
                    ->modalDescription(fn (array $record): string => (string) __(
                        'dberp.plugin_center.confirm.enable',
                        ['name' => (string) ($record['name'] ?? '')],
                    ))
                    ->visible(fn (array $record): bool => in_array(
                        (string) ($record['status'] ?? ''),
                        ['installed', 'disabled', 'failed'],
                        true,
                    ))
                    ->disabled(fn (array $record): bool => ! (bool) ($record['show_enable_action'] ?? false))
                    ->tooltip(fn (array $record): ?string => (string) ($record['enable_blocked_reason'] ?? '') ?: null)
                    ->action(fn (array $record): mixed => $this->enableOfficialPlugin((string) ($record['identifier'] ?? ''))),
                Action::make('update')
                    ->label(__('dberp.plugin_center.actions.update'))
                    ->color('primary')
                    ->icon('heroicon-o-arrow-up-circle')
                    ->requiresConfirmation()
                    ->modalIcon('heroicon-o-arrow-up-circle')
                    ->modalHeading(__('dberp.plugin_center.confirm.update_heading'))
                    ->modalDescription(fn (array $record): string => (string) __(
                        'dberp.plugin_center.confirm.update',
                        [
                            'name' => (string) ($record['name'] ?? ''),
                            'version' => (string) ($record['latest_version'] ?? ''),
                        ],
                    ))
                    ->visible(fn (array $record): bool => ($record['update_state'] ?? null) === 'update_available')
                    ->disabled(fn (array $record): bool => ! (bool) ($record['show_update_action'] ?? false)
                        || ($this->pluginUpdateInProgress
                            && $this->updatingPluginCode === ($record['identifier'] ?? null)))
                    ->tooltip(fn (array $record): ?string => (string) ($record['update_blocked_reason'] ?? '') ?: null)
                    ->action(fn (array $record): mixed => $this->updateOfficialPlugin(
                        (string) ($record['identifier'] ?? ''),
                        filled($record['latest_version'] ?? null) ? (string) $record['latest_version'] : null,
                    )),
                Action::make('details')
                    ->label(__('dberp.plugin_center.details.action_label'))
                    ->icon('heroicon-o-information-circle')
                    ->slideOver()
                    ->modalWidth(Width::Large)
                    ->modalHeading(fn (array $record): string => (string) ($record['name'] ?? ''))
                    ->modalDescription(__('dberp.plugin_center.details.description'))
                    ->modalContent(fn (array $record): View => view('filament.host-plugin-center.plugin-detail-panel', [
                        'record' => $record,
                        'guidanceBlocks' => $guidanceFormatter->blocksForModal($record),
                        'settingsBlocks' => $settingsPanelFormatter->blocksForPanel($record),
                        'fullSettingsUrl' => $settingsPanelFormatter->fullSettingsUrl($record),
                    ]))
                    ->modalSubmitAction(false)
                    ->modalCancelActionLabel(__('filament-actions::view.single.modal.actions.close.label')),
                ActionGroup::make([
                    Action::make('settings')
                        ->label(__('dberp.plugin_center.actions.settings'))
                        ->icon('heroicon-o-cog-6-tooth')
                        ->url(fn (array $record): ?string => filled($record['settings_url'] ?? null)
                            ? (string) $record['settings_url']
                            : null)
                        ->disabled(fn (array $record): bool => ! (bool) ($record['show_settings_action'] ?? false))
                        ->tooltip(fn (array $record): ?string => (string) ($record['settings_blocked_reason'] ?? '') ?: null),
                    Action::make('disable')
                        ->label(__('dberp.plugin_center.actions.disable'))
                        ->color('warning')
                        ->icon('heroicon-o-pause-circle')
                        ->requiresConfirmation()
                        ->modalIcon('heroicon-o-pause-circle')
                        ->modalIconColor('warning')
                        ->modalHeading(__('dberp.plugin_center.confirm.disable_heading'))
                        ->modalDescription(fn (array $record): string => (string) __(
                            'dberp.plugin_center.confirm.disable',
                            ['name' => (string) ($record['name'] ?? '')],
                        ))
                        ->visible(fn (array $record): bool => ($record['status'] ?? null) === 'enabled')
                        ->disabled(fn (array $record): bool => ! (bool) ($record['show_disable_action'] ?? false))
                        ->tooltip(fn (array $record): ?string => (string) ($record['disable_blocked_reason'] ?? '') ?: null)
                        ->action(fn (array $record): mixed => $this->disableOfficialPlugin((string) ($record['identifier'] ?? ''))),
                ])
                    ->label(__('dberp.plugin_center.actions.more'))
                    ->tooltip(__('dberp.plugin_center.actions.more')),
            ]);
    }

    /**
     * @return array<string, array<string, mixed>>
     */
    private function installedPluginRecords(?string $search = null, array $filters = []): array
    {
        $records = [];

        foreach (app(HostPluginCenterDisplay::class)->installedPluginRows() as $row) {
            $identifier = (string) ($row['identifier'] ?? '');

            if ($identifier === '') {
                continue;
            }

            if (filled($search) && ! Str::contains(
                Str::lower(implode(' ', [
                    $identifier,
                    (string) ($row['name'] ?? ''),
                    (string) ($row['version'] ?? ''),
                ])),
                Str::lower((string) $search),
            )) {
                continue;
            }

            $statusFilter = $filters['status']['value'] ?? null;

            if (filled($statusFilter) && ($row['status'] ?? null) !== $statusFilter) {
                continue;
            }

            $updateFilter = $filters['update_state']['value'] ?? null;

            if (filled($updateFilter) && ($row['update_state'] ?? null) !== $updateFilter) {
                continue;
            }

            $records[$identifier] = $row;
        }

        return $records;
    }
}
