<?php

namespace App\Providers;

use App\Models\Customer;
use App\Models\CustomerObject;
use App\Models\Job;
use App\Models\JobPhoto;
use App\Models\Setting;
use App\Models\User;
use App\Models\Vehicle;
use App\Policies\JobPolicy;
use App\Services\AlertService;
use App\Services\Diagnostic\DiagnosticManager;
use App\Services\Diagnostic\DiagnosticPayloadSanitizer;
use App\Services\Diagnostic\DiagnosticReporterRegistry;
use App\Services\Extension\DashboardWidgetRegistry;
use App\Services\Extension\NavigationRegistry;
use App\Services\ForecastService;
use App\Services\ModuleManager;
use App\Services\RetentionService;
use App\Services\SchneespurUpdater;
use App\Services\SeasonService;
use App\Services\Weather\BrightSkyProvider;
use App\Services\Weather\MetNorwayProvider;
use App\Services\Weather\OpenMeteoApiProvider;
use App\Services\Weather\OpenMeteoFreeProvider;
use App\Services\Weather\WeatherProviderRegistry;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\URL;
use Illuminate\Support\Facades\View;
use Illuminate\Http\Middleware\TrustProxies;
use Illuminate\Http\Request;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     */
    public function register(): void
    {
        $this->app->singleton(AlertService::class);
        $this->app->singleton(DashboardWidgetRegistry::class);
        $this->app->singleton(NavigationRegistry::class);
        $this->app->singleton(DiagnosticPayloadSanitizer::class);
        $this->app->singleton(DiagnosticReporterRegistry::class, fn ($app) => new DiagnosticReporterRegistry($app));
        $this->app->singleton(DiagnosticManager::class);
        $this->app->singleton(ModuleManager::class, fn ($app) => new ModuleManager($app));
        $this->app->singleton(WeatherProviderRegistry::class, function ($app) {
            $registry = new WeatherProviderRegistry($app);
            $registry->register('openmeteo_free', OpenMeteoFreeProvider::class);
            $registry->register('openmeteo_api', OpenMeteoApiProvider::class);
            $registry->register('brightsky', BrightSkyProvider::class);
            $registry->register('met_norway', MetNorwayProvider::class);

            return $registry;
        });

        if (empty(config('app.key'))) {
            config(['app.key' => 'base64:'.base64_encode(random_bytes(32))]);
        }
    }

    /**
     * Bootstrap any application services.
     */
    public function boot(): void
    {
        TrustProxies::at('*');
        TrustProxies::withHeaders(
            Request::HEADER_X_FORWARDED_FOR | Request::HEADER_X_FORWARDED_HOST
        );

        if (str_starts_with(config('app.url'), 'https://')) {
            URL::forceScheme('https');
        }

        $locale = Setting::get('default_locale');
        if ($locale && in_array($locale, ['de', 'en'], true)) {
            App::setLocale($locale);
        }

        Gate::policy(Job::class, JobPolicy::class);

        Route::bind('driver', fn (string $value) => User::drivers()->findOrFail($value));
        Route::model('serviceJob', Job::class);
        Route::model('object', CustomerObject::class);

        View::composer('layouts.admin', function ($view) {
            try {
                $view->with('alertCount', app(AlertService::class)->openCount());
            } catch (\Exception) {
                $view->with('alertCount', 0);
            }
        });

        $this->registerCoreNavigation();
        $this->registerCoreDashboardWidgets();

        $this->app->booted(function () {
            app(ModuleManager::class)->boot();
        });
    }

    private function registerCoreNavigation(): void
    {
        $nav = app(NavigationRegistry::class);

        $nav->addGroup('top', '', 0);
        $nav->addGroup('stammdaten', __('admin.nav_group_master_data'), 10);
        $nav->addGroup('einsaetze', __('admin.nav_group_operations'), 20);
        $nav->addGroup('auswertungen', __('admin.nav_group_reports'), 30);
        $nav->addGroup('system', __('admin.nav_group_system'), 40);

        // Top-level
        $nav->addItem(
            group: 'top',
            slug: 'dashboard',
            label: __('admin.nav_dashboard'),
            route: 'admin.dashboard',
            icon: 'M2.25 12l8.954-8.955a1.126 1.126 0 011.591 0L21.75 12M4.5 9.75v10.125c0 .621.504 1.125 1.125 1.125H9.75v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21h4.125c.621 0 1.125-.504 1.125-1.125V9.75M8.25 21h8.25',
            order: 10,
            activePattern: 'admin.dashboard',
        );

        // Stammdaten
        $nav->addItem(
            group: 'stammdaten',
            slug: 'customers',
            label: __('admin.nav_customers'),
            route: 'admin.customers.index',
            icon: 'M15 19.128a9.38 9.38 0 002.625.372 9.337 9.337 0 004.121-.952 4.125 4.125 0 00-7.533-2.493M15 19.128v-.003c0-1.113-.285-2.16-.786-3.07M15 19.128v.106A12.318 12.318 0 018.624 21c-2.331 0-4.512-.645-6.374-1.766l-.001-.109a6.375 6.375 0 0111.964-3.07M12 6.375a3.375 3.375 0 11-6.75 0 3.375 3.375 0 016.75 0zm8.25 2.25a2.625 2.625 0 11-5.25 0 2.625 2.625 0 015.25 0z',
            order: 10,
            activePattern: 'admin.customers.*',
        );
        $nav->addItem(
            group: 'stammdaten',
            slug: 'drivers',
            label: __('admin.nav_drivers'),
            route: 'admin.drivers.index',
            icon: 'M15.75 6a3.75 3.75 0 11-7.5 0 3.75 3.75 0 017.5 0zM4.501 20.118a7.5 7.5 0 0114.998 0A17.933 17.933 0 0112 21.75c-2.676 0-5.216-.584-7.499-1.632z',
            order: 20,
            activePattern: 'admin.drivers.*&!admin.drivers.archived',
        );
        $nav->addItem(
            group: 'stammdaten',
            slug: 'archived-drivers',
            label: __('admin.nav_archived_drivers'),
            route: 'admin.drivers.archived',
            icon: 'M20.25 7.5l-.625 10.632a2.25 2.25 0 01-2.247 2.118H6.622a2.25 2.25 0 01-2.247-2.118L3.75 7.5M10 11.25h4M3.375 7.5h17.25c.621 0 1.125-.504 1.125-1.125v-1.5c0-.621-.504-1.125-1.125-1.125H3.375c-.621 0-1.125.504-1.125 1.125v1.5c0 .621.504 1.125 1.125 1.125z',
            order: 30,
            activePattern: 'admin.drivers.archived',
        );
        $nav->addItem(
            group: 'stammdaten',
            slug: 'vehicles',
            label: __('admin.nav_vehicles'),
            route: 'admin.vehicles.index',
            icon: 'M8.25 18.75a1.5 1.5 0 01-3 0m3 0a1.5 1.5 0 00-3 0m3 0h6m-9 0H3.375a1.125 1.125 0 01-1.125-1.125V14.25m17.25 4.5a1.5 1.5 0 01-3 0m3 0a1.5 1.5 0 00-3 0m3 0H6.375c-.621 0-1.125-.504-1.125-1.125V14.25m17.25 0V6.375c0-.621-.504-1.125-1.125-1.125H4.125c-.621 0-1.125.504-1.125 1.125v7.875m18 0h-1.5m-17.25 0h1.5',
            order: 40,
            activePattern: 'admin.vehicles.*',
        );

        // Einsätze
        $nav->addItem(
            group: 'einsaetze',
            slug: 'jobs',
            label: __('admin.nav_jobs'),
            route: 'admin.jobs.index',
            icon: 'M9 12h3.75M9 15h3.75M9 18h3.75m3 .75H18a2.25 2.25 0 002.25-2.25V6.108c0-1.135-.845-2.098-1.976-2.192a48.424 48.424 0 00-1.123-.08m-5.801 0c-.065.21-.1.433-.1.664 0 .414.336.75.75.75h4.5a.75.75 0 00.75-.75 2.25 2.25 0 00-.1-.664m-5.8 0A2.251 2.251 0 0113.5 2.25H15c1.012 0 1.867.668 2.15 1.586m-5.8 0c-.376.023-.75.05-1.124.08C9.095 4.01 8.25 4.973 8.25 6.108V8.25m0 0H4.875c-.621 0-1.125.504-1.125 1.125v11.25c0 .621.504 1.125 1.125 1.125h9.75c.621 0 1.125-.504 1.125-1.125V9.375c0-.621-.504-1.125-1.125-1.125H8.25zM6.75 12h.008v.008H6.75V12zm0 3h.008v.008H6.75V15zm0 3h.008v.008H6.75V18z',
            order: 10,
            routeCheck: 'admin.jobs.index',
            activePattern: 'admin.jobs.*',
        );
        $nav->addItem(
            group: 'einsaetze',
            slug: 'workshifts',
            label: __('admin.nav_workshifts'),
            route: 'admin.workshifts.index',
            icon: 'M8.25 6.75h12M8.25 12h12m-12 5.25h12M3.75 6.75h.007v.008H3.75V6.75zm.375 0a.375.375 0 11-.75 0 .375.375 0 01.75 0zM3.75 12h.007v.008H3.75V12zm.375 0a.375.375 0 11-.75 0 .375.375 0 01.75 0zm-.375 5.25h.007v.008H3.75v-.008zm.375 0a.375.375 0 11-.75 0 .375.375 0 01.75 0z',
            order: 20,
            routeCheck: 'admin.workshifts.index',
            activePattern: 'admin.workshifts.*',
        );

        // Auswertungen
        $nav->addItem(
            group: 'auswertungen',
            slug: 'overview-daily',
            label: __('admin.nav_overview_daily'),
            route: 'admin.overview.daily',
            icon: 'M6.75 3v2.25M17.25 3v2.25M3 18.75V7.5a2.25 2.25 0 012.25-2.25h13.5A2.25 2.25 0 0121 7.5v11.25m-18 0A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75m-18 0v-7.5A2.25 2.25 0 015.25 9h13.5A2.25 2.25 0 0121 11.25v7.5m-9-6h.008v.008H12v-.008zM12 15h.008v.008H12V15zm0 2.25h.008v.008H12v-.008zM9.75 15h.008v.008H9.75V15zm0 2.25h.008v.008H9.75v-.008zM7.5 15h.008v.008H7.5V15zm0 2.25h.008v.008H7.5v-.008zm6.75-4.5h.008v.008h-.008v-.008zm0 2.25h.008v.008h-.008V15zm0 2.25h.008v.008h-.008v-.008zm2.25-4.5h.008v.008H16.5v-.008zm0 2.25h.008v.008H16.5V15z',
            order: 10,
            routeCheck: 'admin.overview.daily',
            activePattern: 'admin.overview.daily',
        );
        $nav->addItem(
            group: 'auswertungen',
            slug: 'overview-monthly',
            label: __('admin.nav_overview_monthly'),
            route: 'admin.overview.monthly',
            icon: 'M6.75 3v2.25M17.25 3v2.25M3 18.75V7.5a2.25 2.25 0 012.25-2.25h13.5A2.25 2.25 0 0121 7.5v11.25m-18 0A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75m-18 0v-7.5A2.25 2.25 0 015.25 9h13.5A2.25 2.25 0 0121 11.25v7.5||M3 11.25h18',
            order: 20,
            routeCheck: 'admin.overview.monthly',
            activePattern: 'admin.overview.monthly',
        );
        $nav->addItem(
            group: 'auswertungen',
            slug: 'overview-driver-report',
            label: __('admin.nav_overview_driver_report'),
            route: 'admin.overview.driver-report',
            icon: 'M15.75 6a3.75 3.75 0 11-7.5 0 3.75 3.75 0 017.5 0zM4.501 20.118a7.5 7.5 0 0114.998 0A17.933 17.933 0 0112 21.75c-2.676 0-5.216-.584-7.499-1.632z',
            order: 30,
            routeCheck: 'admin.overview.driver-report',
            activePattern: 'admin.overview.driver-report',
        );
        $nav->addItem(
            group: 'auswertungen',
            slug: 'overview-customer-report',
            label: __('admin.nav_overview_customer_report'),
            route: 'admin.overview.customer-report',
            icon: 'M2.25 21h19.5m-18-18v18m10.5-18v18m6-13.5V21M6.75 6.75h.75m-.75 3h.75m-.75 3h.75m3-6h.75m-.75 3h.75m-.75 3h.75M6.75 21v-3.375c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21M3 3h12m-.75 4.5H21m-3.75 3.75h.008v.008h-.008v-.008zm0 3h.008v.008h-.008v-.008zm0 3h.008v.008h-.008v-.008z',
            order: 40,
            routeCheck: 'admin.overview.customer-report',
            activePattern: 'admin.overview.customer-report',
        );
        $nav->addItem(
            group: 'auswertungen',
            slug: 'exports-csv',
            label: __('admin.nav_exports'),
            route: 'admin.exports.csv',
            icon: 'M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m.75 12l3 3m0 0l3-3m-3 3v-6m-1.5-9H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z',
            order: 50,
            routeCheck: 'admin.exports.csv',
            activePattern: 'admin.exports.*',
        );

        // System
        $nav->addItem(
            group: 'system',
            slug: 'alerts',
            label: __('admin.nav_alerts'),
            route: 'admin.alerts.index',
            icon: 'M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z',
            order: 10,
            routeCheck: 'admin.alerts.index',
            activePattern: 'admin.alerts.*',
            badge: 'alertCount',
        );
        $nav->addItem(
            group: 'system',
            slug: 'gps-status',
            label: __('admin.nav_gps_status'),
            route: 'admin.owntracks.overview',
            icon: 'M15 10.5a3 3 0 11-6 0 3 3 0 016 0z||M19.5 10.5c0 7.142-7.5 11.25-7.5 11.25S4.5 17.642 4.5 10.5a7.5 7.5 0 1115 0z',
            order: 20,
            routeCheck: 'admin.owntracks.overview',
            activePattern: 'admin.owntracks.*',
        );
        $nav->addItem(
            group: 'system',
            slug: 'dsgvo',
            label: __('admin.nav_dsgvo'),
            route: 'admin.dsgvo.index',
            icon: 'M9 12.75L11.25 15 15 9.75m-3-7.036A11.959 11.959 0 013.598 6 11.99 11.99 0 003 9.749c0 5.592 3.824 10.29 9 11.623 5.176-1.332 9-6.03 9-11.622 0-1.31-.21-2.571-.598-3.751h-.152c-3.196 0-6.1-1.248-8.25-3.285z',
            order: 30,
            activePattern: 'admin.dsgvo.*',
        );
        $nav->addItem(
            group: 'system',
            slug: 'help',
            label: __('admin.nav_help'),
            route: 'admin.help.index',
            icon: 'M9.879 7.519c1.171-1.025 3.071-1.025 4.242 0 1.172 1.025 1.172 2.687 0 3.712-.203.179-.43.326-.67.442-.745.361-1.45.999-1.45 1.827v.75M12 18.75h.007v.008H12v-.008z||M21 12a9 9 0 11-18 0 9 9 0 0118 0z',
            order: 40,
            routeCheck: 'admin.help.index',
            activePattern: 'admin.help.*',
        );
        $nav->addItem(
            group: 'system',
            slug: 'settings',
            label: __('admin.nav_settings'),
            route: 'admin.settings.index',
            icon: 'M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.324.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 011.37.49l1.296 2.247a1.125 1.125 0 01-.26 1.431l-1.003.827c-.293.24-.438.613-.431.992a6.759 6.759 0 010 .255c-.007.378.138.75.43.99l1.005.828c.424.35.534.954.26 1.43l-1.298 2.247a1.125 1.125 0 01-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.57 6.57 0 01-.22.128c-.331.183-.581.495-.644.869l-.213 1.28c-.09.543-.56.941-1.11.941h-2.594c-.55 0-1.02-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 01-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 01-1.369-.49l-1.297-2.247a1.125 1.125 0 01.26-1.431l1.004-.827c.292-.24.437-.613.43-.992a6.932 6.932 0 010-.255c.007-.378-.138-.75-.43-.99l-1.004-.828a1.125 1.125 0 01-.26-1.43l1.297-2.247a1.125 1.125 0 011.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.087.22-.128.332-.183.582-.495.644-.869l.214-1.281z||M15 12a3 3 0 11-6 0 3 3 0 016 0z',
            order: 50,
            activePattern: 'admin.settings.*',
        );
        $nav->addItem(
            group: 'system',
            slug: 'modules',
            label: __('admin.nav_modules'),
            route: 'admin.settings.modules.index',
            icon: 'M21 7.5l-9-5.25L3 7.5m18 0l-9 5.25m9-5.25v9l-9 5.25M3 7.5l9 5.25M3 7.5v9l9 5.25m0-9v9',
            order: 51,
            activePattern: 'admin.settings.modules.*',
        );
    }

    private function registerCoreDashboardWidgets(): void
    {
        $registry = app(DashboardWidgetRegistry::class);

        $registry->registerWidget('onboarding-checklist', [
            'label' => 'Onboarding Checklist',
            'view' => 'admin.dashboard.widgets.onboarding-checklist',
            'order' => 10,
            'size' => 'full',
            'condition' => function () {
                if (Setting::get('onboarding_dismissed') === '1') {
                    return false;
                }
                $customerCount = Customer::count();
                $driverCount = User::drivers()->count();
                $vehicleCount = Vehicle::count();
                $cronLastRun = cache()->get('cron.last_run');
                $cronOk = $cronLastRun && $cronLastRun->diffInMinutes(now()) < 5;
                $mailConfigured = ! empty(config('mail.mailers.smtp.host'));
                $onboarding = [
                    'company'   => ! empty(Setting::get('company_name')),
                    'driver'    => $driverCount > 0,
                    'customer'  => $customerCount > 0,
                    'vehicle'   => $vehicleCount > 0,
                    'email'     => $mailConfigured,
                    'cron'      => $cronOk,
                ];
                $onboardingComplete = ! in_array(false, $onboarding, true);
                if ($onboardingComplete) {
                    Setting::set('onboarding_dismissed', '1');
                    return false;
                }
                return true;
            },
            'dataCallback' => function () {
                $customerCount = Customer::count();
                $driverCount = User::drivers()->count();
                $vehicleCount = Vehicle::count();
                $cronLastRun = cache()->get('cron.last_run');
                $cronOk = $cronLastRun && $cronLastRun->diffInMinutes(now()) < 5;
                $mailConfigured = ! empty(config('mail.mailers.smtp.host'));
                return [
                    'onboarding' => [
                        'company'   => ! empty(Setting::get('company_name')),
                        'driver'    => $driverCount > 0,
                        'customer'  => $customerCount > 0,
                        'vehicle'   => $vehicleCount > 0,
                        'email'     => $mailConfigured,
                        'cron'      => $cronOk,
                    ],
                ];
            },
        ]);

        $registry->registerWidget('cron-warning', [
            'label' => 'Cron Warning',
            'view' => 'admin.dashboard.widgets.cron-warning',
            'order' => 20,
            'size' => 'full',
            'condition' => function () {
                $cronLastRun = cache()->get('cron.last_run');
                return ! ($cronLastRun && $cronLastRun->diffInMinutes(now()) < 5);
            },
            'dataCallback' => null,
        ]);

        $registry->registerWidget('stat-cards', [
            'label' => 'Statistics',
            'view' => 'admin.dashboard.widgets.stat-cards',
            'order' => 30,
            'size' => 'full',
            'dataCallback' => function () {
                return [
                    'customerCount' => Customer::count(),
                    'driverCount' => User::drivers()->count(),
                    'vehicleCount' => Vehicle::count(),
                ];
            },
        ]);

        $registry->registerWidget('retention-hint', [
            'label' => 'Retention Hint',
            'view' => 'admin.dashboard.widgets.retention-hint',
            'order' => 40,
            'size' => 'full',
            'condition' => function () {
                return app(RetentionService::class)->getRetentionStats() !== null;
            },
            'dataCallback' => function () {
                return [
                    'retentionStats' => app(RetentionService::class)->getRetentionStats(),
                ];
            },
        ]);

        $registry->registerWidget('weather-forecast', [
            'label' => 'Weather',
            'view' => 'admin.dashboard.widgets.weather-forecast',
            'order' => 50,
            'size' => 'full',
            'dataCallback' => function () {
                $companyLat = Setting::get('company_lat');
                $companyLon = Setting::get('company_lon');
                $weather = null;
                $weatherMissing = false;

                if ($companyLat && $companyLon) {
                    $weather = app(ForecastService::class)->current((float) $companyLat, (float) $companyLon);
                } else {
                    $weatherMissing = true;
                }

                return [
                    'weather' => $weather,
                    'weatherMissing' => $weatherMissing,
                ];
            },
        ]);

        $registry->registerWidget('season-statistics', [
            'label' => 'Season Statistics',
            'view' => 'admin.dashboard.widgets.season-statistics',
            'order' => 60,
            'size' => 'full',
            'dataCallback' => function () {
                $season = app(SeasonService::class)->currentOrLastSeason();
                $isSqlite = DB::getDriverName() === 'sqlite';
                $monthExpr = $isSqlite
                    ? "CAST(strftime('%m', started_at) AS INTEGER)"
                    : 'MONTH(started_at)';

                $jobsPerMonth = Job::selectRaw("{$monthExpr} as month, COUNT(*) as job_count")
                    ->whereBetween('started_at', [$season->start, $season->end])
                    ->groupByRaw($monthExpr)
                    ->pluck('job_count', 'month');

                $durationExpr = $isSqlite
                    ? "SUM((JULIANDAY(COALESCE(ended_at, started_at)) - JULIANDAY(started_at)) * 1440)"
                    : "SUM(TIMESTAMPDIFF(MINUTE, started_at, COALESCE(ended_at, started_at)))";

                $seasonTotalMinutes = (int) Job::selectRaw("{$durationExpr} as total_minutes")
                    ->whereBetween('started_at', [$season->start, $season->end])
                    ->whereNotNull('ended_at')
                    ->value('total_minutes');

                $seasonJobCount = Job::whereBetween('started_at', [$season->start, $season->end])->count();

                return [
                    'season' => $season,
                    'jobsPerMonth' => $jobsPerMonth,
                    'seasonTotalMinutes' => $seasonTotalMinutes,
                    'seasonJobCount' => $seasonJobCount,
                ];
            },
        ]);

        $registry->registerWidget('driver-ranking', [
            'label' => 'Driver Ranking',
            'view' => 'admin.dashboard.widgets.driver-ranking',
            'order' => 70,
            'size' => 'full',
            'dataCallback' => function () {
                $season = app(SeasonService::class)->currentOrLastSeason();
                $isSqlite = DB::getDriverName() === 'sqlite';
                $durationExpr = $isSqlite
                    ? "SUM((JULIANDAY(COALESCE(ended_at, started_at)) - JULIANDAY(started_at)) * 1440)"
                    : "SUM(TIMESTAMPDIFF(MINUTE, started_at, COALESCE(ended_at, started_at)))";

                $drivers = User::withAnonymized()
                    ->drivers()
                    ->withCount(['serviceJobs as season_jobs' => fn ($q) => $q->whereBetween('started_at', [$season->start, $season->end])])
                    ->get();

                $driverMinutes = Job::selectRaw("user_id, {$durationExpr} as total_minutes")
                    ->whereBetween('started_at', [$season->start, $season->end])
                    ->whereNotNull('ended_at')
                    ->groupBy('user_id')
                    ->pluck('total_minutes', 'user_id');

                $driverRanking = $drivers->map(function ($driver) use ($driverMinutes) {
                    return (object) [
                        'driver' => $driver,
                        'season_jobs' => $driver->season_jobs,
                        'total_minutes' => (int) ($driverMinutes[$driver->id] ?? 0),
                    ];
                })->sortByDesc('season_jobs')->values();

                return ['driverRanking' => $driverRanking];
            },
        ]);

        $registry->registerWidget('recent-jobs', [
            'label' => 'Recent Jobs',
            'view' => 'admin.dashboard.widgets.recent-jobs',
            'order' => 80,
            'size' => 'full',
            'dataCallback' => function () {
                return [
                    'recentJobs' => Job::with(['customer', 'customerObject.customer', 'user' => fn ($q) => $q->withAnonymized()])
                        ->whereNotNull('ended_at')
                        ->latest('started_at')
                        ->take(10)
                        ->get(),
                ];
            },
        ]);

        $registry->registerWidget('system-status', [
            'label' => 'System Status',
            'view' => 'admin.dashboard.widgets.system-status',
            'order' => 90,
            'size' => 'full',
            'dataCallback' => function () {
                $pendingQueueJobs = 0;
                $failedQueueJobs = 0;
                try {
                    if (Schema::hasTable('jobs')) {
                        $pendingQueueJobs = DB::table('jobs')->count();
                    }
                    if (Schema::hasTable('failed_jobs')) {
                        $failedQueueJobs = DB::table('failed_jobs')->count();
                    }
                } catch (\Throwable) {
                }

                return [
                    'pendingQueueJobs' => $pendingQueueJobs,
                    'failedQueueJobs' => $failedQueueJobs,
                    'photoCount' => JobPhoto::count(),
                ];
            },
        ]);

        $registry->registerWidget('update-check', [
            'label' => 'Update Check',
            'view' => 'admin.dashboard.widgets.update-check',
            'order' => 100,
            'size' => 'full',
            'condition' => function () {
                if (! function_exists('sodium_crypto_sign_verify_detached')) {
                    return false;
                }
                try {
                    return (new SchneespurUpdater)->getState() !== null;
                } catch (\Throwable) {
                    return false;
                }
            },
            'dataCallback' => function () {
                return [
                    'updateState' => (new SchneespurUpdater)->getState(),
                ];
            },
        ]);

        $registry->registerWidget('alert-cards', [
            'label' => 'Alerts',
            'view' => 'admin.dashboard.widgets.alert-cards',
            'order' => 110,
            'size' => 'full',
            'condition' => function () {
                return Route::has('admin.alerts.index');
            },
            'dataCallback' => function () {
                $alertService = app(AlertService::class);
                $alertCounts = $alertService->counts();
                $alertTypes = [
                    'missing_gps' => [
                        'border' => 'border-red-500',
                        'bg' => 'bg-red-50',
                        'text' => 'text-red-700',
                        'count_text' => 'text-red-600',
                        'recentJobs' => $alertCounts['missing_gps'] > 0
                            ? $alertService->missingGpsQuery()->with('customer')->latest('started_at')->take(3)->get()
                            : collect(),
                    ],
                    'missing_weather' => [
                        'border' => 'border-orange-500',
                        'bg' => 'bg-orange-50',
                        'text' => 'text-orange-700',
                        'count_text' => 'text-orange-600',
                        'recentJobs' => $alertCounts['missing_weather'] > 0
                            ? $alertService->missingWeatherQuery()->with('customer')->latest('started_at')->take(3)->get()
                            : collect(),
                    ],
                    'overdue' => [
                        'border' => 'border-yellow-500',
                        'bg' => 'bg-yellow-50',
                        'text' => 'text-yellow-700',
                        'count_text' => 'text-yellow-600',
                        'recentJobs' => $alertCounts['overdue'] > 0
                            ? $alertService->overdueQuery()->with('customer')->latest('started_at')->take(3)->get()
                            : collect(),
                    ],
                ];

                return [
                    'alertCounts' => $alertCounts,
                    'alertTypes' => $alertTypes,
                ];
            },
        ]);
    }
}
