<?php

namespace App\Livewire;

use App\Livewire\Concerns\ResolvesCustomer;
use App\Models\SecurityBlock;
use Livewire\Attributes\Layout;
use Livewire\Attributes\On;
use Livewire\Component;

/**
 * Die Sperrliste der eigenen Instanzen — das Ziel, auf das die Mail aus
 * BlockAddress verlinkt (route('portal.security'), siehe deren
 * SecurityBlockMail), und der Ort, an dem ein Kunde eine eigene
 * Fehlalarm-Sperre selbst vorzeitig aufheben kann.
 */
#[Layout('layouts.portal-app')]
class Security extends Component
{
    use ResolvesCustomer;

    /**
     * ConfirmReleaseBlock dispatches this back (R23) — das Modal selbst
     * mutiert nichts. Es ist ohne die Middleware dieser Seite erreichbar
     * (R20), deshalb wird hier — wie im Modal auch, aber unabhaengig davon —
     * erneut geprueft, dass die Sperre zu einer Instanz DIESES Kunden
     * gehoert, statt der uebergebenen uuid zu vertrauen. Eine fremde oder
     * eine Host-Sperre (kein instance_id) gibt es hier nie zu sehen.
     */
    #[On('block-release-confirmed')]
    public function onReleaseConfirmed(string $uuid): void
    {
        $customer = $this->customer();

        $block = SecurityBlock::query()
            ->where('uuid', $uuid)
            ->whereHas('instance', fn ($q) => $q->where('customer_id', $customer?->id))
            ->first();

        abort_if($block === null, 403);

        // Der Datensatz steht in jedem Fall; nur die Firewall kann nachhinken,
        // wenn der Host gerade nicht erreichbar ist. Dann sagen wir das —
        // sonst versucht sich jemand gleich wieder anzumelden und wird
        // wortlos erneut abgewiesen.
        $this->dispatch('notify', message: $block->release(auth()->user())
            ? __('security.blocks_released')
            : __('security.blocks_released_pending'));
    }

    public function render()
    {
        $customer = $this->customer();

        $blocks = $customer
            ? SecurityBlock::query()
                ->whereHas('instance', fn ($q) => $q->where('customer_id', $customer->id))
                ->orderByDesc('blocked_at')
                ->get()
            : collect();

        // Aktiv/Verlauf wird hier gesplittet, nicht per zweiter Abfrage:
        // scopeActive() prueft dieselben zwei Felder, die die Menge schon in
        // der Hand haelt.
        return view('livewire.security', [
            'active' => $blocks->filter(
                fn (SecurityBlock $b) => $b->released_at === null && $b->expires_at->isFuture()
            )->values(),
            'history' => $blocks->filter(
                fn (SecurityBlock $b) => $b->released_at !== null || $b->expires_at->isPast()
            )->values(),
        ]);
    }
}
