<?php

declare(strict_types=1);

namespace App\Providers\Filament;

use App\Filament\Auth\DberpAdminLogin;
use App\Filament\Pages\BusinessParametersSettingsPage;
use App\Filament\Pages\DataInitializationImportPage;
use App\Filament\Pages\DberpCommonShortcutsPreferencesPage;
use App\Filament\Pages\DberpComprehensiveSummaryAnalysisPage;
use App\Filament\Pages\DberpCustomerCreditControlPage;
use App\Filament\Pages\DberpInventoryAnalysisPage;
use App\Filament\Pages\DberpPurchaseAnalysisPage;
use App\Filament\Pages\DberpPurchaseInquiryComparisonPage;
use App\Filament\Pages\DberpSalesAnalysisPage;
use App\Filament\Pages\DberpSettlementAgingAnalysisPage;
use App\Filament\Pages\DberpSettlementAnalysisPage;
use App\Filament\Pages\DberpSystemInformationPage;
use App\Filament\Pages\HostSystemAuthorizationCenterPage;
use App\Filament\Pages\HostSystemUpdateCenterPage;
use App\Filament\Pages\SiteOnboardingCenterPage;
use App\Filament\Pages\SystemBasicSettingsPage;
use App\Filament\Pages\WorkbenchDashboard;
use App\Filament\Support\DberpAdminSidebarNavigationOrder;
use App\Filament\Support\DberpFilamentActionConfigurator;
use App\Http\Controllers\Filament\AdminLocaleSwitchController;
use App\Http\Controllers\Filament\HostSystemUpdateAutoCheckPingController;
use App\Http\Middleware\AssignDberpAuditCorrelation;
use App\Http\Middleware\EnsureDBErpIsInstalled;
use App\Http\Middleware\RegisterDberpPinnedShortcutNavigationItems;
use App\Http\Middleware\SetAdminLocale;
use App\Models\User;
use App\Services\DberpPermissionService;
use App\Services\SupportCenter\HostSystemUpdateStepProgressStore;
use App\Support\DberpMaintenanceDownExceptPaths;
use App\Support\DberpProductBranding;
use App\Support\HostSystemUpdateCenterDisplay;
use Filament\Events\ServingFilament;
use Filament\Forms\Components\DateTimePicker;
use Filament\Http\Middleware\Authenticate;
use Filament\Http\Middleware\AuthenticateSession;
use Filament\Http\Middleware\DisableBladeIconComponents;
use Filament\Http\Middleware\DispatchServingFilamentEvent;
use Filament\Navigation\NavigationGroup;
use Filament\Panel;
use Filament\PanelProvider;
use Filament\Schemas\Schema;
use Filament\Support\Colors\Color;
use Filament\Support\Facades\FilamentTimezone;
use Filament\Support\Facades\FilamentView;
use Filament\Tables\Table;
use Filament\View\PanelsRenderHook;
use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse;
use Illuminate\Cookie\Middleware\EncryptCookies;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken;
use Illuminate\Routing\Middleware\SubstituteBindings;
use Illuminate\Session\Middleware\StartSession;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Route;
use Illuminate\View\Middleware\ShareErrorsFromSession;

class AdminPanelProvider extends PanelProvider
{
    public function boot(): void
    {
        $this->configureFilamentDomesticDateTimeDisplay();
        DberpFilamentActionConfigurator::registerDefaults();
        $this->registerAdminLocaleSwitcherRenderHook();
        $this->registerAdminOfficialFeedbackRenderHook();
        $this->registerAdminLocaleSwitcherOnLoginRenderHook();
        $this->registerLoginFilingFooterRenderHook();
        $this->registerAdminSidebarWidthLocaleStyles();
        $this->registerAdminTopbarUtilityStyles();
        $this->registerHostSystemUpdateAutoCheckRenderHook();
    }

    public function panel(Panel $panel): Panel
    {
        return $panel
            ->default()
            ->id('admin')
            ->path(trim((string) config('dberp.admin.panel_path', ''), '/'))
            // 关闭 Inter 拉丁子集 preload，避免中文后台首屏触发 Chrome「preloaded but not used」警告。
            ->font(null, null, null, [])
            ->login(DberpAdminLogin::class)
            ->loginRouteSlug('/')
            ->homeUrl(fn (): string => WorkbenchDashboard::getUrl(panel: 'admin'))
            ->viteTheme('resources/css/filament/admin/theme.css')
            ->darkMode(false)
            ->spaUrlExceptions([
                '*locale*',
            ])
            ->brandName(fn (): string => app(DberpProductBranding::class)->displayName())
            ->brandLogo(view('filament.brand-logo'))
            ->brandLogoHeight('auto')
            ->colors([
                'primary' => Color::hex('#1D4ED8'),
                'info' => Color::hex('#1D4ED8'),
                'success' => Color::hex('#16A34A'),
                'warning' => Color::hex('#F59E0B'),
                'danger' => Color::hex('#DC2626'),
                'gray' => Color::hex('#9CA3AF'),
            ])
            ->globalSearch(true)
            ->globalSearchResourceOptIn()
            ->navigationGroups($this->adminNavigationGroups())
            ->routes(function (): void {
                /** @var array<string, string> $locales */
                $locales = config('dberp.admin.locales', []);

                Route::get('locale/{locale}', AdminLocaleSwitchController::class)
                    ->whereIn('locale', array_keys($locales))
                    ->name('locale.switch');

                Route::post('host-system/update-auto-check/ping', HostSystemUpdateAutoCheckPingController::class)
                    ->name('host-system.update-auto-check.ping');
            })
            ->discoverResources(in: app_path('Filament/Resources'), for: 'App\Filament\Resources')
            ->pages([
                WorkbenchDashboard::class,
                DberpCommonShortcutsPreferencesPage::class,
                DberpCustomerCreditControlPage::class,
                DberpSettlementAgingAnalysisPage::class,
                DberpComprehensiveSummaryAnalysisPage::class,
                DberpSalesAnalysisPage::class,
                DberpPurchaseAnalysisPage::class,
                DberpInventoryAnalysisPage::class,
                DberpSettlementAnalysisPage::class,
                DberpPurchaseInquiryComparisonPage::class,
                DberpSystemInformationPage::class,
                SiteOnboardingCenterPage::class,
                HostSystemAuthorizationCenterPage::class,
                HostSystemUpdateCenterPage::class,
                SystemBasicSettingsPage::class,
                BusinessParametersSettingsPage::class,
                DataInitializationImportPage::class,
            ])
            ->middleware([
                EncryptCookies::class,
                AddQueuedCookiesToResponse::class,
                StartSession::class,
                AssignDberpAuditCorrelation::class,
                SetAdminLocale::class,
                AuthenticateSession::class,
                ShareErrorsFromSession::class,
                EnsureDBErpIsInstalled::class,
                VerifyCsrfToken::class,
                SubstituteBindings::class,
                DisableBladeIconComponents::class,
                DispatchServingFilamentEvent::class,
            ])
            ->authMiddleware([
                Authenticate::class,
                RegisterDberpPinnedShortcutNavigationItems::class,
            ]);
    }

    /**
     * @return list<NavigationGroup>
     */
    private function adminNavigationGroups(): array
    {
        return DberpAdminSidebarNavigationOrder::navigationGroups();
    }

    /**
     * 后台 Filament 日期/时间：国内常用数字格式 + 展示时区（见 config app.display_timezone）。
     */
    private function configureFilamentDomesticDateTimeDisplay(): void
    {
        Event::listen(ServingFilament::class, static function (): void {
            FilamentTimezone::set((string) config('app.display_timezone'));
        });

        Table::configureUsing(static function (Table $table): void {
            $table
                ->defaultDateDisplayFormat('Y-m-d')
                ->defaultDateTimeDisplayFormat('Y-m-d H:i:s')
                ->defaultTimeDisplayFormat('H:i:s');
        });

        Schema::configureUsing(static function (Schema $schema): void {
            $schema
                ->defaultDateDisplayFormat('Y-m-d')
                ->defaultDateTimeDisplayFormat('Y-m-d H:i:s')
                ->defaultTimeDisplayFormat('H:i:s');
        });

        DateTimePicker::configureUsing(static function (DateTimePicker $component): void {
            $component
                ->defaultDateDisplayFormat('Y-m-d')
                ->defaultDateTimeDisplayFormat('Y-m-d H:i')
                ->defaultDateTimeWithSecondsDisplayFormat('Y-m-d H:i:s')
                ->defaultTimeDisplayFormat('H:i')
                ->defaultTimeWithSecondsDisplayFormat('H:i:s');
        });
    }

    /**
     * 语言切换挂在 GLOBAL_SEARCH_AFTER（与顶栏全局搜索同一区域右侧）。
     */
    private function registerAdminLocaleSwitcherRenderHook(): void
    {
        FilamentView::registerRenderHook(
            PanelsRenderHook::GLOBAL_SEARCH_AFTER,
            fn (): string => view('filament.hooks.admin-locale-switch')->render(),
        );
    }

    /**
     * 顶栏用户菜单前：官方问题反馈外链（新标签打开，不采集系统数据）。
     * 挂在用户菜单前，避免与全局搜索、语言切换同排争抢宽度。
     */
    private function registerAdminOfficialFeedbackRenderHook(): void
    {
        FilamentView::registerRenderHook(
            PanelsRenderHook::USER_MENU_BEFORE,
            function (): string {
                if (! Auth::check()) {
                    return '';
                }

                return view('filament.hooks.admin-official-feedback-link')->render();
            },
        );
    }

    private function registerAdminLocaleSwitcherOnLoginRenderHook(): void
    {
        FilamentView::registerRenderHook(
            PanelsRenderHook::SIMPLE_LAYOUT_START,
            fn (): string => view('filament.hooks.admin-locale-switch-login')->render(),
            scopes: DberpAdminLogin::class,
        );
    }

    private function registerLoginFilingFooterRenderHook(): void
    {
        // 备案信息直接嵌入 simple.blade.php 的 fi-simple-main-ctn 内，无需 hook
    }

    /**
     * 中文界面收窄侧栏为配置宽度；英文等保持 Filament 默认（panel 不调用 sidebarWidth，内联为 20rem）。
     * 必须在 STYLES_AFTER 注入，以覆盖布局内联 :root 变量。
     */
    private function registerAdminSidebarWidthLocaleStyles(): void
    {
        FilamentView::registerRenderHook(
            PanelsRenderHook::STYLES_AFTER,
            fn (): string => view('filament.hooks.admin-sidebar-width-locale')->render(),
        );
    }

    private function registerAdminTopbarUtilityStyles(): void
    {
        FilamentView::registerRenderHook(
            PanelsRenderHook::STYLES_AFTER,
            fn (): string => view('filament.hooks.admin-topbar-utility-styles')->render(),
        );
    }

    /**
     * 后台布局末尾注入轻量 ping：仅对已登录且具备系统更新中心查看权的用户触发 opportunistic 检查。
     */
    private function registerHostSystemUpdateAutoCheckRenderHook(): void
    {
        FilamentView::registerRenderHook(
            PanelsRenderHook::LAYOUT_END,
            function (): string {
                if (! (bool) config('dberp.system_update.auto_check.enabled', true)) {
                    return '';
                }

                $user = Auth::user();

                if (! $user instanceof User) {
                    return '';
                }

                if (! app(DberpPermissionService::class)->allows($user, DberpPermissionService::VIEW_HOST_SYSTEM_UPDATE)) {
                    return '';
                }

                if (
                    app(DberpMaintenanceDownExceptPaths::class)->isSystemUpdateCenterRequest(request())
                    || app(HostSystemUpdateCenterDisplay::class)->isUpdateRunning()
                    || app(HostSystemUpdateStepProgressStore::class)->hasNonTerminalSession()
                ) {
                    return '';
                }

                return view('filament.hooks.host-system-update-auto-check-ping', [
                    'pingUrl' => route('filament.admin.host-system.update-auto-check.ping'),
                    'timeoutMs' => max(1000, (int) config('dberp.system_update.auto_check.timeout_seconds', 2) * 1000),
                ])->render();
            },
        );
    }
}
