<?php

namespace App\Livewire\Modals;

use App\Models\AuditEvent;
use App\Models\Server;
use App\Services\HardeningService;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Str;
use LivewireUI\Modal\ModalComponent;
use Throwable;

/**
 * Preview + confirm modal for one server-hardening TOGGLE (R5).
 *
 * `$enable` is the desired feature state — true turns the feature on, false off.
 * mount() loads a direction-aware title + the exact root commands (preview) so the
 * operator sees what will run BEFORE applying. apply() runs it, AUDITs, notifies,
 * asks the page to reload its hardening state, and shows the result.
 */
class HardeningAction extends ModalComponent
{
    public int $serverId;

    public string $action;

    /** Desired feature state: true = aktivieren, false = deaktivieren. */
    public bool $enable;

    public string $heading = '';

    public string $description = '';

    public bool $done = false;

    public bool $ok = false;

    public string $output = '';

    public ?string $error = null;

    public function mount(int $serverId, string $action, bool $enable): void
    {
        abort_unless(auth()->user()?->can('manage-network'), 403);

        $this->serverId = $serverId;
        $this->action = $action;
        $this->enable = $enable;

        $server = Server::find($serverId);
        if (! $server) {
            $this->error = __('common.server_not_found');

            return;
        }

        try {
            $hardening = app(HardeningService::class);
            $this->heading = $hardening->title($action, $enable);
            $this->description = $hardening->description($action, $enable);
        } catch (Throwable $e) {
            $this->error = $e->getMessage();
        }
    }

    public static function modalMaxWidth(): string
    {
        return 'lg';
    }

    public function apply(): void
    {
        abort_unless(auth()->user()?->can('manage-network'), 403);

        if ($this->error !== null || $this->done) {
            return;
        }

        $server = Server::find($this->serverId);
        if (! $server) {
            $this->error = __('common.server_not_found');

            return;
        }

        try {
            $result = app(HardeningService::class)->apply($server, $this->action, $this->enable);
        } catch (Throwable $e) {
            $this->done = true;
            $this->ok = false;
            $this->output = $e->getMessage();

            return;
        }

        $this->done = true;
        $this->ok = $result['ok'];
        // Clean result only — no raw command output on success; a short reason on failure.
        $this->output = $this->ok ? '' : Str::limit(trim($result['output']) ?: __('modals.hardening_action.error_unknown'), 200);

        AuditEvent::create([
            'user_id' => Auth::id(),
            'server_id' => $server->id,
            'actor' => Auth::user()?->name ?? 'system',
            'action' => 'harden.'.$this->action.($this->enable ? '.on' : '.off'),
            'target' => $server->name.' · '.$this->heading.($this->ok ? '' : ' '.__('modals.hardening_action.audit_failed_suffix')),
            'ip' => request()->ip(),
        ]);

        if ($this->ok) {
            $this->dispatch('hardeningApplied');
            $this->dispatch('notify', message: __('modals.hardening_action.notify_applied', ['action' => $this->heading]));
        } else {
            $this->dispatch('notify', message: __('modals.hardening_action.notify_failed', ['action' => $this->heading]));
        }
    }

    public function render()
    {
        return view('livewire.modals.hardening-action');
    }
}
