<?php

namespace App\Providers;

use Illuminate\Auth\Notifications\ResetPassword;
use Illuminate\Auth\Notifications\VerifyEmail;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Config;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\URL;
use Illuminate\Support\ServiceProvider;
use RuntimeException;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     */
    public function register(): void
    {
        //
    }

    /**
     * Bootstrap any application services.
     */
    public function boot(): void
    {
        Schema::defaultStringLength(191);
        $this->forceConfiguredUrl();

        VerifyEmail::createUrlUsing(function (object $notifiable): string {
            return $this->customerUrl(URL::temporarySignedRoute(
                'verification.verify',
                Carbon::now()->addMinutes(Config::get('auth.verification.expire', 60)),
                [
                    'id' => $notifiable->getKey(),
                    'hash' => sha1($notifiable->getEmailForVerification()),
                ],
                false
            ));
        });

        VerifyEmail::toMailUsing(function (object $notifiable, string $url): MailMessage {
            return (new MailMessage)
                ->subject('Confirmez votre adresse e-mail - La Valise à Macarons')
                ->greeting('Bonjour,')
                ->line('Merci d’avoir créé votre compte La Valise à Macarons.')
                ->line('Pour continuer votre commande avec ce compte, confirmez votre adresse e-mail.')
                ->action('Confirmer mon adresse e-mail', $url)
                ->markdown('emails.auth.verify-email');
        });

        ResetPassword::toMailUsing(function (object $notifiable, string $token): MailMessage {
            $url = $this->customerUrl(route('password.reset', [
                'token' => $token,
                'email' => $notifiable->getEmailForPasswordReset(),
            ], false));

            return (new MailMessage)
                ->subject('Choisissez un nouveau mot de passe - La Valise à Macarons')
                ->greeting('Bonjour,')
                ->line('Vous avez demandé à changer le mot de passe de votre compte La Valise à Macarons.')
                ->line('Cliquez sur le bouton ci-dessous pour choisir un nouveau mot de passe.')
                ->action('Changer mon mot de passe', $url)
                ->line('Ce lien est valable pendant 60 minutes.')
                ->line('Si vous n’avez rien demandé, vous pouvez ignorer ce message.');
        });
    }

    protected function forceConfiguredUrl(): void
    {
        $appUrl = rtrim((string) config('app.url'), '/');

        if ($appUrl === '' || $this->isLocalUrl($appUrl)) {
            if (! app()->environment('production')) {
                return;
            }

            throw new RuntimeException('APP_URL de production invalide: ' . ($appUrl ?: 'vide'));
        }

        if (app()->environment('production')) {
            $googleRedirect = (string) config('services.google.redirect');
            if ($googleRedirect !== '' && $this->isLocalUrl($googleRedirect)) {
                throw new RuntimeException('GOOGLE_REDIRECT_URI de production invalide: ' . $googleRedirect);
            }

            $boxQrBaseUrl = (string) config('services.box_qr.public_base_url');
            if ($boxQrBaseUrl !== '' && $this->isLocalUrl($boxQrBaseUrl)) {
                throw new RuntimeException('BOX_QR_PUBLIC_BASE_URL de production invalide: ' . $boxQrBaseUrl);
            }

            if (config('mail.default') === 'smtp' && $this->isLocalHost((string) config('mail.mailers.smtp.host'))) {
                throw new RuntimeException('MAIL_HOST de production pointe vers une machine locale.');
            }
        }

        URL::forceRootUrl($appUrl);

        if (str_starts_with($appUrl, 'https://')) {
            URL::forceScheme('https');
            Config::set('session.secure', true);
        }
    }

    protected function isLocalUrl(string $url): bool
    {
        return $this->isLocalHost((string) parse_url($url, PHP_URL_HOST));
    }

    protected function isLocalHost(string $host): bool
    {
        $host = strtolower(trim($host));

        if (in_array($host, [
            'localhost',
            '127.0.0.1',
            '::1',
        ], true)) {
            return true;
        }

        return preg_match('#^(10\.|192\.168\.|172\.(1[6-9]|2\d|3[0-1])\.)#', $host) === 1;
    }

    protected function customerUrl(string $path): string
    {
        if (preg_match('#^https?://#i', $path) === 1) {
            return $path;
        }

        return rtrim((string) config('app.customer_url'), '/') . '/' . ltrim($path, '/');
    }
}
