<?php

namespace App\Providers;

use App\Core\Product\Events\AccountCreated;
use App\Events\CommunicationEvent;
use App\Events\DomainProvisioningCompleted;
use App\Events\DomainProvisioningFailed;
use App\Events\DomainProvisioningProgress;
use App\Events\DomainProvisioningStarted;
use App\Events\DomainRegistered;
use App\Events\InvoiceCancelled;
use App\Events\InvoiceCreated;
use App\Events\InvoicePaid;
use App\Events\InvoiceRefunded;
use App\Events\InvoiceStatusChanged;
use App\Events\ProductProvisioningCompleted;
use App\Events\TranslationUpdated;
use App\Listeners\Search\ReindexOnTranslationUpdate;
use App\Events\ProductProvisioningFailed;
use App\Events\ProductProvisioningProgress;
use App\Events\ProductProvisioningStarted;
use App\Events\TicketCreatedByAdmin;
use App\Events\TicketCreatedByClient;
use App\Events\TicketRepliedByAdmin;
use App\Events\TicketRepliedByClient;
use App\Listeners\CommunicationDispatcher;
use App\Listeners\LogCompletedJobListener;
use App\Listeners\LogDomainRegistration;
use App\Listeners\LogTicketCreated;
use App\Listeners\LogTicketReplied;
use App\Listeners\QueueTicketEmails;
use App\Listeners\HandleInvoiceStatusChange;
use App\Listeners\SendInvoiceCancelledNotification;
use App\Listeners\SendInvoiceCreatedNotification;
use App\Listeners\SendInvoicePaidNotification;
use App\Listeners\UpdateProvisioningLogCompleted;
use App\Listeners\UpdateProvisioningLogFailed;
use App\Listeners\UpdateProvisioningLogProgress;
use App\Listeners\UpdateProvisioningLogStarted;
use App\Models\Client;
use App\Models\Invoice;
use App\Models\Log;
use App\Models\Ticket;
use App\Models\TicketReply;
use App\Observers\ClientObserver;
use App\Observers\InvoiceObserver;
use App\Observers\LogObserver;
use App\Observers\TicketObserver;
use App\Observers\TicketReplyObserver;
use Illuminate\Auth\Events\Registered;
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use Illuminate\Queue\Events\JobProcessed;

class EventServiceProvider extends ServiceProvider
{
    /**
     * The event to listener mappings for the application.
     *
     * @var array<class-string, array<int, class-string>>
     */
    /**
     * Event subscribers.
     */
    protected $subscribe = [
        \App\Listeners\TicketIntegrationNotifier::class,
        \App\Listeners\TicketEscalationListener::class,
        \App\Listeners\AiStaffListener::class,
        \App\Listeners\CancellationListener::class,
        \App\Listeners\OrderEventListener::class,
        \App\Listeners\DispatchLegalInvoiceListener::class,
        \App\Listeners\Backup\ForwardBackupNotification::class,
    ];

    protected $listen = [
        Registered::class => [
            SendEmailVerificationNotification::class,
        ],

        // PRC-780 — SocialiteProviders/Microsoft driver kaydı (Microsoft ile giriş)
        \SocialiteProviders\Manager\SocialiteWasCalled::class => [
            \SocialiteProviders\Microsoft\MicrosoftExtendSocialite::class.'@handle',
        ],

        // PRC-75: legal invoice issued → email customer with PDF attachment
        \App\Events\LegalInvoiceIssued::class => [
            \App\Listeners\SendLegalInvoiceEmail::class,
        ],

        // PRC-299: co-order DNS auto-setup (domain register + hosting in same order)
        \App\Events\DomainProvisioningCompleted::class => [
            \App\Listeners\SetupDnsForCoOrderListener::class,
        ],

        // Queue olayları - Tamamlanan job'ları logla
        JobProcessed::class => [
            LogCompletedJobListener::class,
        ],

        // Modül olayları
        DomainRegistered::class => [
            LogDomainRegistration::class,
        ],

        AccountCreated::class => [
            // Hesap oluşturulduğunda çalışacak listener'lar
        ],

        // Product Provisioning olayları
        ProductProvisioningStarted::class => [
            UpdateProvisioningLogStarted::class,
        ],
        ProductProvisioningProgress::class => [
            UpdateProvisioningLogProgress::class,
        ],
        ProductProvisioningCompleted::class => [
            UpdateProvisioningLogCompleted::class,
        ],
        ProductProvisioningFailed::class => [
            UpdateProvisioningLogFailed::class,
        ],

        // Domain Provisioning olayları
        DomainProvisioningStarted::class => [
            UpdateProvisioningLogStarted::class,
        ],
        DomainProvisioningProgress::class => [
            UpdateProvisioningLogProgress::class,
        ],
        DomainProvisioningCompleted::class => [
            UpdateProvisioningLogCompleted::class,
        ],
        DomainProvisioningFailed::class => [
            UpdateProvisioningLogFailed::class,
        ],

        // Ticket olayları (Email observer yerine manuel dispatch kullanıyoruz)
        TicketCreatedByAdmin::class => [
            LogTicketCreated::class,
        ],
        TicketCreatedByClient::class => [
            LogTicketCreated::class,
        ],
        TicketRepliedByAdmin::class => [
            LogTicketReplied::class,
            \App\Listeners\TicketFirstResponderAssignment::class, // PRC-794
        ],
        TicketRepliedByClient::class => [
            LogTicketReplied::class,
        ],

        // Billing olayları
        InvoiceCreated::class => [
            SendInvoiceCreatedNotification::class,
        ],
        InvoicePaid::class => [
            SendInvoicePaidNotification::class,
        ],
        InvoiceCancelled::class => [
            SendInvoiceCancelledNotification::class,
            // PRC-845 (edge #23) — iptalde reseller komisyonunu geri al
            \App\Listeners\ReverseResellerCommission::class,
        ],
        // PRC-845 (edge #23) — iadede reseller komisyonunu geri al
        InvoiceRefunded::class => [
            \App\Listeners\ReverseResellerCommission::class,
        ],
        InvoiceStatusChanged::class => [
            HandleInvoiceStatusChange::class,
        ],

        // İletişim olayları (PRC-622) — tek bildirim olayı, kanal kararı dispatcher'da.
        // OrderCreated → order_created admin bildirimi de buradan işlenir
        // (config/communication_events.php 'events' köprüsü, boot()'ta kurulur).
        CommunicationEvent::class => [
            CommunicationDispatcher::class,
        ],

        // Translation olayları - Search indexer tetikle
        TranslationUpdated::class => [
            ReindexOnTranslationUpdate::class,
        ],

        // PRC-648: Domain sync immediate (deferred=false) bildirimleri.
        // Cron batch (deferred=true) flushNotifications'ta toplu gönderilir.
        \App\EventHooks\Domain\DomainSyncStatusChanged::class => [
            [\App\Listeners\SendDomainSyncNotification::class, 'onStatusChanged'],
        ],
        \App\EventHooks\Domain\DomainSyncExpiryDateChanged::class => [
            [\App\Listeners\SendDomainSyncNotification::class, 'onExpiryChanged'],
        ],
    ];

    /**
     * Register any events for your application.
     */
    public function boot(): void
    {
        // Client model observer
        Client::observe(ClientObserver::class);

        // Ticket model observer
        Ticket::observe(TicketObserver::class);
        TicketReply::observe(TicketReplyObserver::class);

        // Invoice model observer
        Invoice::observe(InvoiceObserver::class);

        // Log model observer (PRC-194 hash chain + append-only enforcement)
        Log::observe(LogObserver::class);

        // PRC-622: config/communication_events.php 'events' haritası →
        // domain event'leri CommunicationEvent'e köprüle. Closure'lar burada
        // (boot'ta) kurulur — config dosyasında closure yok (config:cache uyumlu).
        $mapper = $this->app->make(\App\Services\Communication\CommunicationEventMapper::class);
        foreach (config('communication_events.events', []) as $eventClass => $mappings) {
            if (! is_string($eventClass) || ! is_array($mappings) || $mappings === []) {
                continue;
            }

            \Illuminate\Support\Facades\Event::listen($eventClass, function (object $event) use ($mapper, $mappings): void {
                foreach ($mappings as $mapping) {
                    if (! is_array($mapping)) {
                        continue;
                    }

                    $communicationEvent = $mapper->mapFromEvent($mapping, $event);
                    if ($communicationEvent !== null) {
                        event($communicationEvent);
                    }
                }
            });
        }
    }

    /**
     * Determine if events and listeners should be automatically discovered.
     */
    public function shouldDiscoverEvents(): bool
    {
        return false;
    }
}
