<?php

use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;
use Illuminate\Console\Scheduling\Schedule;

return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        web: __DIR__.'/../routes/web.php',
        api: __DIR__.'/../routes/api.php',
        commands: __DIR__.'/../routes/console.php',
        health: '/up',
    )
    ->withMiddleware(function (Middleware $middleware): void {
        // Middleware aliases
        $middleware->alias([
            'admin' => \App\Http\Middleware\AdminMiddleware::class,
            'reseller' => \App\Http\Middleware\ResellerMiddleware::class,
            'maintenance' => \App\Http\Middleware\CheckMaintenanceMode::class,
            'check.query.limit' => \App\Http\Middleware\CheckDnsQueryLimit::class,
            'check.zone.suspended' => \App\Http\Middleware\CheckZoneSuspended::class,
            'api.auth' => \App\Http\Middleware\ApiAuthenticate::class,
            'api.rate' => \App\Http\Middleware\ApiRateLimit::class,
            'api.ability' => \App\Http\Middleware\ApiCheckAbility::class,
            'api.log' => \App\Http\Middleware\ApiLogRequest::class,
            'verify.captcha' => \App\Http\Middleware\VerifyCaptcha::class,
            '2fa' => \App\Http\Middleware\TwoFactorAuthentication::class,
            'verified' => \App\Http\Middleware\EnsureEmailIsVerifiedIfRequired::class,
        ]);

        // Exclude Stripe webhook from CSRF verification
        $middleware->validateCsrfTokens(except: [
            'stripe/webhook',
        ]);

        // Adaugă maintenance check DUPĂ autentificare (append)
        // Astfel Auth::check() va funcționa corect
        $middleware->web(append: [
            \App\Http\Middleware\CheckMaintenanceMode::class,
            \App\Http\Middleware\SetLocale::class,
            \App\Http\Middleware\ForceHttps::class,
        ]);
    })
    ->withSchedule(function (Schedule $schedule): void {
        // Funcție helper pentru a crea expresie cron validă din interval în minute
        // Minute pot fi doar 0-59, așa că intervale > 59 trebuie convertite în ore
        $createCronExpression = function (int $intervalMinutes): string {
            if ($intervalMinutes <= 0) {
                $intervalMinutes = 30; // Valoare default de siguranță
            }

            if ($intervalMinutes <= 59) {
                // Interval în minute (ex: */15, */30)
                return "*/{$intervalMinutes} * * * *";
            } elseif ($intervalMinutes < 1440) {
                // Interval în ore (ex: la fiecare 2 ore = 0 */2 * * *)
                $hours = max(1, (int) floor($intervalMinutes / 60));
                return "0 */{$hours} * * *";
            } else {
                // Interval zilnic sau mai mare - rulează o dată pe zi la 00:30
                return "30 0 * * *";
            }
        };

        // Health check Name Servers - interval configurabil din admin
        if (setting('cron_nameserver_check_enabled', true)) {
            $interval = (int) setting('cron_nameserver_check_interval', 5);
            $schedule->command('nameservers:check-health')
                ->cron($createCronExpression($interval));
        }

        // ✨ Dispatch statistici DNS pentru IERI - interval și limită configurabile
        // Colectează statistici pentru ziua anterioară (complete)
        if (setting('cron_statistics_yesterday_enabled', true)) {
            $interval = (int) setting('cron_statistics_yesterday_interval', 30);
            $limit = (int) setting('cron_statistics_yesterday_limit', 20);

            $schedule->command("dns:dispatch-statistics --limit={$limit}")
                ->cron($createCronExpression($interval))
                ->withoutOverlapping(3)
                ->onSuccess(function () {
                    \Illuminate\Support\Facades\Log::info('Dispatch statistici DNS (ieri) completat');
                })
                ->onFailure(function () {
                    \Illuminate\Support\Facades\Log::error('Dispatch statistici DNS (ieri) a eșuat');
                });
        }

        // ✨ Dispatch statistici DNS pentru AZI - interval și limită configurabile
        // Colectează statistici LIVE pentru ziua curentă (actualizare continuă)
        if (setting('cron_statistics_today_enabled', true)) {
            $interval = (int) setting('cron_statistics_today_interval', 15);
            $limit = (int) setting('cron_statistics_today_limit', 10);

            $schedule->call(function () use ($limit) {
                \Illuminate\Support\Facades\Artisan::call('dns:dispatch-statistics', [
                    '--date' => now()->format('Y-m-d'),
                    '--limit' => $limit,
                    '--force' => true
                ]);
            })
                ->name('dispatch-statistics-today')
                ->cron($createCronExpression($interval))
                ->withoutOverlapping(3)
                ->onSuccess(function () {
                    \Illuminate\Support\Facades\Log::info('Dispatch statistici DNS (azi) completat');
                })
                ->onFailure(function () {
                    \Illuminate\Support\Facades\Log::error('Dispatch statistici DNS (azi) a eșuat');
                });
        }

        // Verificare zone DNS offline - interval configurabil din admin
        if (setting('cron_dns_health_check_enabled', true)) {
            $interval = setting('cron_dns_health_check_interval', 30);
            $notify = setting('cron_dns_health_check_notify', true) ? '--notify' : '';

            $command = $schedule->command("dns:check-zones-health {$notify}")
                ->withoutOverlapping(10)
                ->onSuccess(function () {
                    \Illuminate\Support\Facades\Log::info('Verificare zone DNS completată');
                })
                ->onFailure(function () {
                    \Illuminate\Support\Facades\Log::error('Verificare zone DNS a eșuat');
                });

            // Setează intervalul în funcție de valoare
            if ($interval >= 1440) {
                // Zilnic sau mai mult
                $command->daily();
            } elseif ($interval >= 60) {
                // Ore (convertește minutele în ore)
                $hours = floor($interval / 60);
                $command->cron("0 */{$hours} * * *");
            } else {
                // Minute (sub 60)
                $command->cron("*/{$interval} * * * *");
            }
        }

        // Actualizare cursuri BNR - zilnic la 13:30 (după publicarea oficială BNR la 13:00)
        $schedule->command('currencies:update-bnr')->dailyAt('13:30');

        // Backup automat - Full backup zilnic la 00:00
        $schedule->command('backup:database --type=full')
            ->dailyAt('00:00')
            ->onSuccess(function () {
                \Illuminate\Support\Facades\Log::info('Backup automat full completat cu succes');
            })
            ->onFailure(function () {
                \Illuminate\Support\Facades\Log::error('Backup automat full a eșuat');
            });

        // Backup incremental la fiecare 6 ore
        $schedule->command('backup:database --type=incremental')
            ->cron('0 */6 * * *')
            ->onSuccess(function () {
                \Illuminate\Support\Facades\Log::info('Backup automat incremental completat cu succes');
            })
            ->onFailure(function () {
                \Illuminate\Support\Facades\Log::error('Backup automat incremental a eșuat');
            });

        // Cleanup backup-uri vechi (>10 zile) - zilnic la 01:00
        $schedule->command('backup:cleanup --days=10')
            ->dailyAt('01:00')
            ->onSuccess(function () {
                \Illuminate\Support\Facades\Log::info('Cleanup backup-uri completat cu succes');
            });

        // Sincronizare zone DNS către nameservere - la fiecare oră
        $schedule->command('zones:sync-to-nameservers')
            ->hourly()
            ->withoutOverlapping(10)
            ->onSuccess(function () {
                \Illuminate\Support\Facades\Log::info('Sincronizare zone DNS completată');
            })
            ->onFailure(function () {
                \Illuminate\Support\Facades\Log::error('Sincronizare zone DNS a eșuat');
            });

        // Verificare și fix SOA records - zilnic la 02:00
        $schedule->command('dns:sync-soa')
            ->dailyAt('02:00')
            ->withoutOverlapping(10)
            ->onSuccess(function () {
                \Illuminate\Support\Facades\Log::info('Sincronizare SOA records completată');
            })
            ->onFailure(function () {
                \Illuminate\Support\Facades\Log::error('Sincronizare SOA records a eșuat');
            });

        // Verificare duplicate DNS records - zilnic la 03:00
        $schedule->command('dns:check-duplicates')
            ->dailyAt('03:00')
            ->onSuccess(function () {
                \Illuminate\Support\Facades\Log::info('Verificare duplicate DNS completată');
            })
            ->onFailure(function () {
                \Illuminate\Support\Facades\Log::error('Verificare duplicate DNS a eșuat');
            });

        // Cleanup cache Laravel - zilnic la 04:00
        $schedule->command('cache:prune-stale-tags')
            ->dailyAt('04:00')
            ->onSuccess(function () {
                \Illuminate\Support\Facades\Log::info('Cleanup cache completat');
            });

        // Cleanup failed jobs vechi (>7 zile) - zilnic la 04:30
        $schedule->command('queue:prune-failed --hours=168')
            ->dailyAt('04:30')
            ->onSuccess(function () {
                \Illuminate\Support\Facades\Log::info('Cleanup failed jobs completat');
            });

        // Restart queue workers - zilnic la 05:00 (pentru a preveni memory leaks)
        $schedule->command('queue:restart')
            ->dailyAt('05:00')
            ->onSuccess(function () {
                \Illuminate\Support\Facades\Log::info('Queue workers restarted');
            });
    })
    ->withExceptions(function (Exceptions $exceptions): void {
        //
    })->create();
