<?php

namespace Modules\Bms\Services\Notifications;

use Modules\Bms\Entities\BmsSetting;
use Modules\Bms\Services\Contracts\NotificationServiceContract;

/**
 * Notification routing matrix (scenario 2.10). A per-business setting maps each
 * update type to the channels that should fire (email / whatsapp / sms / push).
 * All channels route through the ERP shared comms layer via NotificationService.
 */
class NotificationRouter
{
    public const SETTING_KEY = 'notification_matrix';

    /** Default channels per update type (used until overridden in P1). */
    public const DEFAULTS = [
        'lead_selection'      => ['whatsapp'],
        'change_request'      => ['push', 'email'],
        'change_decided'      => ['whatsapp', 'email'],
        'booking_confirmed'   => ['whatsapp', 'email'],
        'booking_cancelled'   => ['whatsapp', 'email'],
        'booking_rescheduled' => ['whatsapp', 'email'],
        'payment_received'    => ['whatsapp'],
        'contract_sent'       => ['whatsapp', 'email'],
        'document_ready'      => ['email'],
        'visit_booked'        => ['whatsapp', 'email'],
        'task_assigned'       => ['push'],
        'maintenance_status'  => ['email'],
        'transfer_accepted'   => ['push'],
        'new_booking'         => ['push', 'email'],
    ];

    /** The full matrix for a business (overrides merged over defaults). */
    public function matrix(int $businessId): array
    {
        $saved = BmsSetting::get($businessId, self::SETTING_KEY, []);
        return is_array($saved) ? array_merge(self::DEFAULTS, $saved) : self::DEFAULTS;
    }

    public function channelsFor(int $businessId, string $updateType): array
    {
        $m = $this->matrix($businessId);
        return $m[$updateType] ?? self::DEFAULTS[$updateType] ?? ['email'];
    }

    /**
     * Route an update through its configured channels.
     *
     * @param  string|array  $to
     */
    public function notify(int $businessId, string $updateType, $to, string $subject, string $body, array $data = [], ?string $dedupeKey = null): array
    {
        $channels = $this->channelsFor($businessId, $updateType);
        if (empty($channels) || empty($to)) {
            return ['skipped' => true];
        }

        return app(NotificationServiceContract::class)->send($businessId, [
            'to'          => $to,
            'channels'    => $channels,
            'subject'     => $subject,
            'body'        => $body,
            'data'        => $data,
            'update_type' => $updateType,
            'dedupe_key'  => $dedupeKey,
        ]);
    }
}
