<?php

namespace App\Livewire\Portal;

use App\Domain\Notification\Models\NotificationPreference;
use App\Domain\Shared\Models\DeviceToken;
use App\Livewire\Portal\Concerns\PortalScreen;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Component;

/**
 * Which notifications reach the member, on which channel — and the devices
 * currently entitled to receive them.
 *
 * `notification_preferences` has existed with per-event, per-channel columns
 * and no interface anywhere: the table was written to by the deleted API and by
 * nothing else, so in practice every member received everything on every
 * channel with no way to say otherwise.
 *
 * The device list is here too, because push is the one channel a member cannot
 * see the recipients of. An old phone, a browser at work, a device someone else
 * now owns — all silently keep receiving until the token rotates.
 */
#[Layout('layouts.portal')]
#[Title('التفضيلات')]
class PortalPreferences extends Component
{
    use PortalScreen;

    /** @var array<string, array<string, bool>> event => channel => enabled */
    public array $preferences = [];

    public string $locale = 'ar';

    /**
     * The events a member can actually choose about.
     *
     * Deliberately not every event_type the system emits: a member cannot
     * usefully opt out of "your payment was received", and offering the choice
     * implies a control that should not exist.
     */
    public const EVENTS = [
        'session_reminder' => 'تذكير بالحصص',
        'attendance_marked' => 'تسجيل الحضور',
        'invoice_issued' => 'فاتورة جديدة',
        'installment_due' => 'قسط مستحق',
        'evaluation_shared' => 'تقييم جديد',
        'document_expiring' => 'مستند على وشك الانتهاء',
        'announcement' => 'إعلانات الأكاديمية',
        'waitlist_offer' => 'توفّر مقعد',
    ];

    public const CHANNELS = [
        'channel_push' => 'إشعار على الهاتف',
        'channel_in_app' => 'داخل التطبيق',
        'channel_email' => 'بريد إلكتروني',
        'channel_sms' => 'رسالة نصية',
    ];

    public function mount(): void
    {
        $this->authorizePortal();

        $this->locale = session('locale', app()->getLocale());

        $existing = NotificationPreference::where('user_id', auth()->id())
            ->get()
            ->keyBy('event_type');

        foreach (array_keys(self::EVENTS) as $event) {
            $row = $existing[$event] ?? null;

            foreach (array_keys(self::CHANNELS) as $channel) {
                // Absent means "not yet chosen", which is opted in — the member
                // has not asked for less, and silently defaulting to off would
                // mean a missed instalment nobody was told about.
                $this->preferences[$event][$channel] = $row ? (bool) $row->{$channel} : true;
            }
        }
    }

    public function save(): void
    {
        $user = auth()->user();

        foreach ($this->preferences as $event => $channels) {
            if (! array_key_exists($event, self::EVENTS)) {
                continue;
            }

            NotificationPreference::updateOrCreate(
                ['user_id' => $user->id, 'event_type' => $event],
                [
                    // academy_id exists on this table since S1's tenancy repair;
                    // without it the row belonged to no tenant.
                    'academy_id' => $user->academy_id,
                    'channel_push' => (bool) ($channels['channel_push'] ?? true),
                    'channel_in_app' => (bool) ($channels['channel_in_app'] ?? true),
                    'channel_email' => (bool) ($channels['channel_email'] ?? true),
                    'channel_sms' => (bool) ($channels['channel_sms'] ?? true),
                ]
            );
        }

        session()->flash('success', __('تم حفظ التفضيلات'));
    }

    public function setLocale(string $locale): void
    {
        if (! in_array($locale, ['ar', 'en'], true)) {
            return;
        }

        // SetLocale reads this on the next request. It was registered nowhere
        // until now, so this session key had no effect on anything.
        session(['locale' => $locale]);

        $this->redirect(route('portal.preferences'), navigate: false);
    }

    public function forgetDevice(int $deviceId): void
    {
        DeviceToken::where('id', $deviceId)
            ->where('user_id', auth()->id())
            ->delete();

        session()->flash('success', __('تم إلغاء تسجيل الجهاز'));
    }

    public function render()
    {
        return view('livewire.portal.portal-preferences', [
            'events' => self::EVENTS,
            'channels' => self::CHANNELS,
            'devices' => DeviceToken::where('user_id', auth()->id())
                ->orderByDesc('last_used_at')
                ->get(),
        ]);
    }
}
