<?php

namespace App\Providers;

use App\Mail\Transport\ElasticEmailApiTransport;
use App\Mail\Transport\GoogleApiTransport;
use App\Mail\Transport\MicrosoftApiTransport;
use App\Mail\Transport\NetcoreApiTransport;
use App\Mail\Transport\PostmarkApiTransport;
use App\Mail\Transport\Smtp2GoApiTransport;
use App\Mail\Transport\SparkPostApiTransport;
use App\Mail\Transport\ToSendApiTransport;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\ServiceProvider;
use Illuminate\Validation\Rules\Password;
use Symfony\Component\Mailer\Bridge\Brevo\Transport\BrevoTransportFactory;
use Symfony\Component\Mailer\Bridge\Sendgrid\Transport\SendgridTransportFactory;
use Symfony\Component\Mailer\Transport\Dsn;
use Symfony\Component\Mailer\Transport\NativeTransportFactory;

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

    /**
     * Bootstrap any application services.
     */
    public function boot(): void
    {
        // Applies to registration, password resets, and profile password
        // changes alike  matches the strength checklist shown on the
        // profile page (lowercase/uppercase/number/symbol/8-char minimum).
        Password::defaults(function () {
            return Password::min(8)->mixedCase()->numbers()->symbols();
        });

        // HTTP API transports Laravel has no native factory for. The API key
        // comes from the mailer config set at runtime by SmtpConfigService.
        Mail::extend('sendgrid', function (array $config = []) {
            $key = $config['key'] ?? config('services.sendgrid.key');

            return (new SendgridTransportFactory)->create(
                new Dsn('sendgrid+api', 'default', $key)
            );
        });

        Mail::extend('brevo', function (array $config = []) {
            $key = $config['key'] ?? config('services.brevo.key');

            return (new BrevoTransportFactory)->create(
                new Dsn('brevo+api', 'default', $key)
            );
        });

        // No official Symfony bridge exists for SparkPost - custom transport.
        Mail::extend('sparkpost', function (array $config = []) {
            $key = $config['key'] ?? config('services.sparkpost.key');

            return new SparkPostApiTransport($key, $config['region'] ?? 'us');
        });

        // No official Symfony bridge exists for Netcore (Pepipost) - custom transport.
        Mail::extend('netcore', function (array $config = []) {
            $key = $config['key'] ?? config('services.netcore.key');

            return new NetcoreApiTransport($key, $config['region'] ?? 'us');
        });

        // Hand-rolled rather than symfony/postmark-mailer so TrackOpens /
        // TrackLinks / MessageStream (exposed in our UI) can be sent.
        Mail::extend('postmark', function (array $config = []) {
            $key = $config['key'] ?? config('services.postmark.token');

            return new PostmarkApiTransport(
                $key,
                (bool) ($config['track_opens'] ?? false),
                $config['track_links'] ?? 'None',
                $config['message_stream'] ?? 'outbound',
            );
        });

        // No official Symfony bridge exists for Elastic Email - custom transport.
        Mail::extend('elastic', function (array $config = []) {
            $key = $config['key'] ?? config('services.elastic.key');

            return new ElasticEmailApiTransport($key, (bool) ($config['is_transactional'] ?? true));
        });

        // No official Symfony bridge exists for SMTP2GO - custom transport.
        Mail::extend('smtp2go', function (array $config = []) {
            $key = $config['key'] ?? config('services.smtp2go.key');

            return new Smtp2GoApiTransport($key);
        });

        // No official Symfony bridge exists for toSend - custom transport.
        Mail::extend('tosend', function (array $config = []) {
            $key = $config['key'] ?? config('services.tosend.key');

            return new ToSendApiTransport($key);
        });

        // PHP's native mail() equivalent: sendmail_path on Unix, or the
        // SMTP/smtp_port php.ini settings on Windows. No credentials at all.
        Mail::extend('phpmail', function () {
            return (new NativeTransportFactory())->create(new Dsn('native', 'default'));
        });

        // No official Symfony bridge exists for the Gmail API - custom
        // transport. Credentials come from the OAuth flow in GoogleOAuthController.
        Mail::extend('gmail', function (array $config = []) {
            return new GoogleApiTransport(
                $config['client_id'] ?? '',
                $config['client_secret'] ?? '',
                $config['refresh_token'] ?? null,
            );
        });

        // No official Symfony bridge exists for the Microsoft Graph API -
        // custom transport. Credentials come from the OAuth flow in
        // MicrosoftOAuthController; on_token_refreshed persists Microsoft's
        // rotating refresh token (set up in SmtpConfigService).
        Mail::extend('outlook', function (array $config = []) {
            return new MicrosoftApiTransport(
                $config['client_id'] ?? '',
                $config['client_secret'] ?? '',
                $config['refresh_token'] ?? null,
                $config['on_token_refreshed'] ?? null,
            );
        });
    }
}
