<x-app-layout>
    <x-slot name="header">
        <div class="flex items-center justify-between gap-4">
            <h2 class="font-semibold text-xl text-gray-800 leading-tight">{{ __('Disk') }}</h2>
            @include('partials.section-access-controls', [
                'sectionAccessEntity' => 'disks',
                'sectionAccessTitle' => __('Disk'),
                'canManageSectionAccess' => $canManageSectionAccess ?? false,
                'sectionAccessUsers' => $sectionAccessUsers ?? collect(),
            ])
        </div>
    </x-slot>

    @php
        $formatSize = static function (int $bytes): string {
            $units = ['B', 'KB', 'MB', 'GB', 'TB'];
            $size = max(0, (float) $bytes);
            $index = 0;

            while ($size >= 1024 && $index < count($units) - 1) {
                $size /= 1024;
                $index++;
            }

            return number_format($size, $index === 0 ? 0 : 1, '.', ' ').' '.$units[$index];
        };

        $ownerNameMap = collect($ownerOptions ?? [])
            ->mapWithKeys(static fn ($row): array => [
                (int) data_get($row, 'id') => (string) data_get($row, 'name'),
            ])
            ->all();
        $folderSegments = $folder !== ''
            ? array_values(array_filter(explode('/', $folder), static fn ($part): bool => trim((string) $part) !== ''))
            : [];
        $folderBreadcrumbs = [];
        $folderPathAccumulator = '';
        foreach ($folderSegments as $segment) {
            $folderPathAccumulator = $folderPathAccumulator === ''
                ? $segment
                : $folderPathAccumulator.'/'.$segment;
            $folderBreadcrumbs[] = [
                'name' => $segment,
                'path' => $folderPathAccumulator,
            ];
        }
    @endphp

    <div class="pb-12">
        <div class="w-full px-6 space-y-4">
            @if (session('success'))
                <div class="rounded-md border border-emerald-200 bg-emerald-50 px-3 py-2 text-sm text-emerald-800">
                    {{ session('success') }}
                </div>
            @endif

            <section class="bg-white border border-gray-200 rounded-xl p-4">
                <form method="GET" action="{{ route('disks.index') }}" class="grid grid-cols-1 gap-3 md:grid-cols-5">
                    <div class="md:col-span-2">
                        <label for="disk-search" class="block text-xs font-medium text-gray-500 uppercase">{{ __('Search') }}</label>
                        <input id="disk-search" type="text" name="q" value="{{ $search }}" placeholder="{{ __('File name, folder, description') }}" class="mt-1 w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500">
                    </div>

                    <div>
                        <label for="disk-folder" class="block text-xs font-medium text-gray-500 uppercase">{{ __('Folder') }}</label>
                        <input id="disk-folder" type="text" name="folder" value="{{ $folder }}" list="disk-folder-options" placeholder="{{ __('For example: shared/contracts') }}" class="mt-1 w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500">
                    </div>

                    @if (($isElevated ?? false) && ($ownerOptions ?? collect())->isNotEmpty())
                        <div>
                            <label for="disk-owner-id" class="block text-xs font-medium text-gray-500 uppercase">{{ __('Owner') }}</label>
                            <select id="disk-owner-id" name="owner_id" class="mt-1 w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500">
                                <option value="">{{ __('All owners') }}</option>
                                @foreach (($ownerOptions ?? collect()) as $ownerOption)
                                    @php
                                        $ownerOptionId = (int) data_get($ownerOption, 'id');
                                        $ownerOptionName = (string) data_get($ownerOption, 'name');
                                    @endphp
                                    <option value="{{ $ownerOptionId }}" @selected((int) ($ownerId ?? 0) === $ownerOptionId)>{{ $ownerOptionName }}</option>
                                @endforeach
                            </select>
                        </div>
                    @endif

                    <div class="flex items-end gap-2">
                        <button type="submit" class="inline-flex items-center rounded-md bg-gray-800 px-4 py-2 text-sm font-medium text-white hover:bg-gray-700">{{ __('Apply') }}</button>
                        <a href="{{ route('disks.index') }}" class="inline-flex items-center rounded-md border border-gray-300 px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50">{{ __('Reset') }}</a>
                    </div>
                </form>
            </section>

            <section class="bg-white border border-gray-200 rounded-xl p-4">
                <div class="flex flex-wrap items-center justify-between gap-2">
                    <div>
                        <h3 class="text-sm font-semibold text-gray-900">{{ __('Explorer') }}</h3>
                        <p class="text-xs text-gray-500">{{ __('Use breadcrumb, path field, and right-click context menu for quick file operations.') }}</p>
                    </div>
                    @if ($folder)
                        <a
                            href="{{ route('disks.index', array_filter(['q' => $search, 'owner_id' => ($ownerId ?? 0) > 0 ? $ownerId : null])) }}"
                            class="inline-flex items-center rounded-md border border-gray-300 px-3 py-1.5 text-xs font-medium text-gray-700 hover:bg-gray-50"
                        >
                            {{ __('Go to root') }}
                        </a>
                    @endif
                </div>
            </section>

            @can('create', \App\Models\Disk::class)
                <section class="bg-white border border-gray-200 rounded-xl p-4">
                    <h3 class="text-sm font-semibold text-gray-900">{{ __('Upload to disk') }}</h3>
                    <form method="POST" action="{{ route('disks.store') }}" enctype="multipart/form-data" class="mt-3 grid grid-cols-1 md:grid-cols-6 gap-3">
                        @csrf

                        <div class="md:col-span-2">
                            <label for="disk-file" class="block text-xs font-medium text-gray-500 uppercase">{{ __('File') }}</label>
                            <input id="disk-file" data-disk-file-input type="file" name="file" required class="sr-only">
                            <div
                                data-disk-dropzone
                                tabindex="0"
                                role="button"
                                aria-controls="disk-file"
                                class="mt-1 flex min-h-[12rem] flex-col items-center justify-center rounded-xl border-2 border-dashed border-slate-300 bg-slate-50 px-5 py-6 text-center text-sm text-gray-600 transition hover:border-indigo-400 hover:bg-indigo-50/40 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-1"
                            >
                                <span data-disk-drop-icon class="mb-2 inline-flex h-12 w-12 items-center justify-center rounded-full border border-indigo-200 bg-white text-indigo-600 shadow-sm">
                                    <x-menu-icon name="fa-solid fa-cloud-arrow-up" class="h-5 w-5" />
                                </span>
                                <p class="font-semibold text-gray-800">{{ __('Drag file here or click to select') }}</p>
                                <p class="mt-1 text-xs text-gray-500">{{ __('Drop file in the center area') }}</p>
                                <p class="mt-1 text-xs text-gray-500">{{ __('Maximum size: 50 MB') }}</p>
                                <p data-disk-selected-file class="mt-2 hidden text-xs font-medium text-indigo-700"></p>
                            </div>
                            <x-input-error class="mt-2" :messages="$errors->get('file')" />
                        </div>

                        <div>
                            <label for="disk-name" class="block text-xs font-medium text-gray-500 uppercase">{{ __('Display name') }}</label>
                            <input id="disk-name" type="text" name="name" value="{{ old('name') }}" class="mt-1 w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500" placeholder="{{ __('Optional') }}">
                            <x-input-error class="mt-2" :messages="$errors->get('name')" />
                        </div>

                        <div>
                            <label for="disk-folder-create" class="block text-xs font-medium text-gray-500 uppercase">{{ __('Folder') }}</label>
                            <input id="disk-folder-create" type="text" name="folder" value="{{ old('folder') }}" list="disk-folder-options" class="mt-1 w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500" placeholder="shared/contracts">
                            <x-input-error class="mt-2" :messages="$errors->get('folder')" />
                        </div>

                        <div class="md:col-span-2">
                            <label for="disk-description" class="block text-xs font-medium text-gray-500 uppercase">{{ __('Description') }}</label>
                            <input id="disk-description" type="text" name="description" value="{{ old('description') }}" class="mt-1 w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500" placeholder="{{ __('Optional') }}">
                            <x-input-error class="mt-2" :messages="$errors->get('description')" />
                        </div>

                        <div class="md:col-span-1 flex items-end">
                            <label class="inline-flex items-center gap-2 text-sm text-gray-700">
                                <input type="hidden" name="is_public" value="0">
                                <input type="checkbox" name="is_public" value="1" class="rounded border-gray-300 text-indigo-600 shadow-sm focus:ring-indigo-500" @checked(old('is_public'))>
                                {{ __('Public') }}
                            </label>
                        </div>

                        <div class="md:col-span-1 flex items-end justify-end">
                            <button type="submit" class="inline-flex items-center rounded-md bg-indigo-600 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-500">{{ __('Upload') }}</button>
                        </div>
                    </form>
                </section>
            @endcan

            <section
                class="relative overflow-hidden rounded-xl border border-gray-200 bg-white"
                data-disk-explorer
                data-current-folder="{{ $folder }}"
                data-current-owner-id="{{ (int) ($ownerId ?? 0) }}"
                data-route-folder-create="{{ route('disks.explorer.folders.create') }}"
                data-route-folder-delete="{{ route('disks.explorer.folders.delete') }}"
                data-route-folder-move="{{ route('disks.explorer.folders.move') }}"
                data-route-folder-copy="{{ route('disks.explorer.folders.copy') }}"
                data-route-file-move-template="{{ route('disks.explorer.files.move', ['disk' => '__DISK__']) }}"
                data-route-file-copy-template="{{ route('disks.explorer.files.copy', ['disk' => '__DISK__']) }}"
                data-route-file-delete-template="{{ route('disks.explorer.files.delete', ['disk' => '__DISK__']) }}"
            >
                <div class="border-b border-gray-200 bg-slate-50/80 p-3">
                    <div class="flex flex-wrap items-center justify-between gap-2">
                        <nav class="max-w-full overflow-x-auto whitespace-nowrap text-sm text-slate-700">
                            <a
                                href="{{ route('disks.index', array_filter(['q' => $search, 'owner_id' => ($ownerId ?? 0) > 0 ? $ownerId : null])) }}"
                                class="inline-flex items-center rounded-md border border-transparent px-1.5 py-0.5 hover:border-slate-200 hover:bg-white"
                            >
                                <x-menu-icon name="fa-solid fa-hard-drive" class="mr-1.5 h-3.5 w-3.5 text-slate-500" />
                                {{ __('Root') }}
                            </a>
                            @foreach ($folderBreadcrumbs as $crumb)
                                <span class="mx-1 text-slate-400">/</span>
                                <a
                                    href="{{ route('disks.index', array_filter(['folder' => $crumb['path'], 'q' => $search, 'owner_id' => ($ownerId ?? 0) > 0 ? $ownerId : null])) }}"
                                    class="inline-flex items-center rounded-md border border-transparent px-1.5 py-0.5 hover:border-slate-200 hover:bg-white {{ $crumb['path'] === $folder ? 'font-semibold text-indigo-700' : '' }}"
                                >
                                    {{ $crumb['name'] }}
                                </a>
                            @endforeach
                        </nav>

                        @can('create', \App\Models\Disk::class)
                            <button
                                type="button"
                                data-explorer-new-folder
                                class="inline-flex items-center gap-1 rounded-md border border-slate-300 bg-white px-2.5 py-1.5 text-xs font-medium text-slate-700 hover:bg-slate-100"
                            >
                                <x-menu-icon name="fa-solid fa-folder-plus" class="h-3.5 w-3.5" />
                                <span>{{ __('Create catalog') }}</span>
                            </button>
                        @endcan
                    </div>

                    <div class="mt-2 flex flex-wrap items-center gap-2">
                        <form class="flex min-w-[18rem] flex-1 items-center gap-2" data-explorer-jump-form>
                            <label for="explorer-path-input" class="sr-only">{{ __('Path') }}</label>
                            <input
                                id="explorer-path-input"
                                type="text"
                                data-explorer-path-input
                                value="{{ $folder }}"
                                class="w-full rounded-md border-slate-300 bg-white px-3 py-1.5 text-sm shadow-sm focus:border-indigo-500 focus:ring-indigo-500"
                                placeholder="{{ __('Path (example: shared/contracts)') }}"
                            >
                            <button
                                type="submit"
                                class="inline-flex items-center rounded-md border border-slate-300 bg-white px-3 py-1.5 text-xs font-medium text-slate-700 hover:bg-slate-100"
                            >
                                {{ __('Open') }}
                            </button>
                            <button
                                type="button"
                                data-explorer-up
                                class="inline-flex items-center rounded-md border border-slate-300 bg-white px-3 py-1.5 text-xs font-medium text-slate-700 hover:bg-slate-100"
                            >
                                {{ __('Up') }}
                            </button>
                        </form>
                    </div>

                    @can('create', \App\Models\Disk::class)
                        <form data-explorer-create-form class="mt-2 hidden flex flex-wrap items-center gap-2 rounded-lg border border-indigo-200 bg-white p-2.5">
                            <span class="text-xs font-medium text-slate-500" data-explorer-create-target>{{ __('Create in root') }}</span>
                            <input
                                type="text"
                                data-explorer-create-name
                                class="min-w-[14rem] flex-1 rounded-md border-slate-300 px-3 py-1.5 text-sm shadow-sm focus:border-indigo-500 focus:ring-indigo-500"
                                placeholder="{{ __('Catalog name') }}"
                            >
                            <button
                                type="submit"
                                data-explorer-create-submit
                                class="inline-flex items-center rounded-md bg-indigo-600 px-3 py-1.5 text-xs font-medium text-white hover:bg-indigo-500"
                            >
                                {{ __('Create') }}
                            </button>
                            <button
                                type="button"
                                data-explorer-create-cancel
                                class="inline-flex items-center rounded-md border border-slate-300 bg-white px-3 py-1.5 text-xs font-medium text-slate-700 hover:bg-slate-100"
                            >
                                {{ __('Cancel') }}
                            </button>
                        </form>
                    @endcan

                    <p data-explorer-status class="mt-2 hidden rounded-md border px-3 py-2 text-xs"></p>
                </div>

                <div class="grid min-h-[34rem] grid-cols-12">
                    <aside class="col-span-12 border-b border-gray-200 bg-slate-50 p-3 lg:col-span-3 lg:border-b-0 lg:border-r">
                        <div class="mb-2 flex items-center justify-between">
                            <h4 class="text-xs font-semibold uppercase tracking-wide text-slate-500">{{ __('Catalogs') }}</h4>
                            <span class="text-[11px] text-slate-500">{{ __('Drag and drop supported') }}</span>
                        </div>

                        <div class="max-h-[30rem] overflow-y-auto pr-1">
                            <a
                                href="{{ route('disks.index', array_filter(['q' => $search, 'owner_id' => ($ownerId ?? 0) > 0 ? $ownerId : null])) }}"
                                data-folder-node
                                data-folder-path=""
                                data-folder-owner-id="{{ (int) ($ownerId ?? 0) }}"
                                draggable="true"
                                class="{{ $folder === '' ? 'bg-indigo-50 text-indigo-700 border-indigo-200' : 'text-slate-700 border-transparent hover:bg-slate-100' }} mb-1 flex items-center gap-2 rounded-md border px-2 py-1.5 text-sm"
                            >
                                <x-menu-icon name="fa-solid fa-hard-drive" class="h-3.5 w-3.5 text-slate-500" />
                                <span class="truncate">{{ __('Root') }}</span>
                            </a>

                            @if (($folderItems ?? collect())->isNotEmpty())
                                <div class="space-y-0.5">
                                    @foreach ($folderItems as $folderItem)
                                        @php
                                            $folderPath = (string) ($folderItem['path'] ?? '');
                                            $folderOwnerId = (int) ($folderItem['owner_id'] ?? 0);
                                            $depth = max(0, substr_count($folderPath, '/'));
                                            $folderKey = (string) ($folderItem['key'] ?? ($folderOwnerId.':'.$folderPath));
                                            $isActiveFolder = $folderPath !== ''
                                                && $folderPath === $folder
                                                && ((int) ($ownerId ?? 0) === 0 || (int) ($ownerId ?? 0) === $folderOwnerId);
                                            $isCatalog = (bool) ($folderItem['is_catalog'] ?? false);
                                            $fileCountKey = $folderOwnerId.':'.$folderPath;
                                            $folderCount = (int) ($folderFileCounts[$fileCountKey] ?? 0);
                                            $folderOwnerName = (string) ($ownerNameMap[$folderOwnerId] ?? '');
                                            $folderUrlParams = array_filter([
                                                'folder' => $folderPath,
                                                'owner_id' => (($isElevated ?? false) && $folderOwnerId > 0) ? $folderOwnerId : null,
                                                'q' => $search !== '' ? $search : null,
                                            ]);
                                        @endphp
                                        <a
                                            href="{{ route('disks.index', $folderUrlParams) }}"
                                            data-folder-node
                                            data-folder-key="{{ $folderKey }}"
                                            data-folder-path="{{ $folderPath }}"
                                            data-folder-owner-id="{{ $folderOwnerId }}"
                                            draggable="true"
                                            class="{{ $isActiveFolder ? 'bg-indigo-50 text-indigo-700 border-indigo-200' : 'text-slate-700 border-transparent hover:bg-slate-100' }} flex items-center gap-2 rounded-md border px-2 py-1.5 text-sm"
                                            style="padding-left: {{ (0.5 + ($depth * 0.75)) }}rem"
                                        >
                                            <x-menu-icon :name="$isCatalog ? 'fa-solid fa-folder' : 'fa-regular fa-folder-open'" class="h-3.5 w-3.5 {{ $isCatalog ? 'text-amber-500' : 'text-slate-400' }}" />
                                            <span class="min-w-0 flex-1 truncate">{{ basename($folderPath) }}</span>
                                            <span class="rounded bg-slate-200 px-1.5 py-0.5 text-[10px] text-slate-600">{{ $folderCount }}</span>
                                            @if (($isElevated ?? false) && $folderOwnerName !== '')
                                                <span class="max-w-[7rem] truncate text-[10px] text-slate-500" title="{{ $folderOwnerName }}">{{ $folderOwnerName }}</span>
                                            @endif
                                        </a>
                                    @endforeach
                                </div>
                            @else
                                <p class="rounded-md border border-dashed border-slate-300 px-2 py-3 text-xs text-slate-500">{{ __('No catalogs yet.') }}</p>
                            @endif
                        </div>
                    </aside>

                    <div class="col-span-12 min-w-0 lg:col-span-9" data-explorer-file-area>
                        <table class="min-w-full divide-y divide-gray-200">
                            <thead class="bg-gray-50">
                                <tr>
                                    <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">{{ __('File') }}</th>
                                    <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">{{ __('Folder') }}</th>
                                    <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">{{ __('Owner') }}</th>
                                    <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">{{ __('Size') }}</th>
                                    <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">{{ __('Visibility') }}</th>
                                    <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">{{ __('Updated') }}</th>
                                    <th class="px-4 py-3 text-right text-xs font-medium text-gray-500 uppercase">{{ __('Actions') }}</th>
                                </tr>
                            </thead>
                            <tbody class="divide-y divide-gray-100 bg-white">
                                @forelse ($disks as $disk)
                                    @php
                                        $iconMeta = $disk->iconMeta();
                                        $extensionBadge = strtoupper((string) ($disk->extension ?: $iconMeta['label']));
                                    @endphp
                                    <tr
                                        class="hover:bg-gray-50"
                                        data-file-row
                                        data-file-id="{{ $disk->id }}"
                                        data-file-owner-id="{{ (int) $disk->owner_id }}"
                                        data-file-folder="{{ (string) ($disk->folder ?? '') }}"
                                        data-preview-url="{{ route('disks.preview', $disk) }}"
                                        draggable="true"
                                    >
                                        <td class="px-4 py-3">
                                            <div class="flex items-start gap-3">
                                                <span
                                                    data-disk-file-icon="{{ $iconMeta['icon'] }}"
                                                    class="{{ $iconMeta['icon_wrapper_class'] }} inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-lg border"
                                                    title="{{ __($iconMeta['label']) }}"
                                                    aria-label="{{ __($iconMeta['label']) }}"
                                                >
                                                    <x-menu-icon :name="$iconMeta['icon']" class="h-4 w-4" />
                                                </span>
                                                <div class="min-w-0">
                                                    <p class="font-medium text-gray-900">{{ $disk->name }}</p>
                                                    <p class="flex flex-wrap items-center gap-1.5 text-xs text-gray-500">
                                                        <span class="{{ $iconMeta['badge_class'] }} inline-flex items-center rounded border px-1.5 py-0.5 text-[10px] font-semibold leading-none">
                                                            {{ $extensionBadge }}
                                                        </span>
                                                        <span class="truncate">{{ $disk->original_name }} · {{ $disk->mime_type ?: 'application/octet-stream' }}</span>
                                                    </p>
                                                    @if ($disk->description)
                                                        <p class="mt-1 text-xs text-gray-500">{{ $disk->description }}</p>
                                                    @endif
                                                </div>
                                            </div>
                                        </td>
                                        <td class="px-4 py-3 text-sm text-gray-700">{{ $disk->folder ?: '—' }}</td>
                                        <td class="px-4 py-3 text-sm text-gray-700">{{ $disk->owner?->name ?? '—' }}</td>
                                        <td class="px-4 py-3 text-sm text-gray-700">{{ $formatSize((int) $disk->size) }}</td>
                                        <td class="px-4 py-3 text-sm text-gray-700">
                                            {{ $disk->is_public ? __('Public') : __('Private') }}
                                        </td>
                                        <td class="px-4 py-3 text-sm text-gray-700">{{ $disk->updated_at?->format('d.m.Y H:i') }}</td>
                                        <td class="px-4 py-3 text-right text-sm">
                                            <div class="inline-flex items-center gap-2">
                                                @if (app(\App\Support\DiskFileManager::class)->canPreviewInCrm($disk))
                                                    <a
                                                        href="{{ route('disks.preview', $disk) }}"
                                                        title="{{ __('Preview') }}"
                                                        aria-label="{{ __('Preview') }}"
                                                        class="inline-flex h-8 w-8 items-center justify-center rounded-md border border-indigo-300 text-indigo-700 transition hover:bg-indigo-50"
                                                    >
                                                        <x-menu-icon name="fa-solid fa-eye" class="h-3.5 w-3.5" />
                                                    </a>
                                                @endif

                                                <button
                                                    type="button"
                                                    data-disk-copy-link
                                                    data-copy-url="{{ route('disks.preview', $disk) }}"
                                                    data-label-default="{{ __('Copy link') }}"
                                                    data-label-copied="{{ __('Copied') }}"
                                                    title="{{ __('Copy link') }}"
                                                    aria-label="{{ __('Copy link') }}"
                                                    class="inline-flex h-8 w-8 items-center justify-center rounded-md border border-sky-300 text-sky-700 transition hover:bg-sky-50"
                                                >
                                                    <x-menu-icon name="fa-solid fa-link" class="h-3.5 w-3.5" />
                                                    <span class="sr-only" data-copy-label>{{ __('Copy link') }}</span>
                                                </button>

                                                <a
                                                    href="{{ route('disks.download', $disk) }}"
                                                    title="{{ __('Download') }}"
                                                    aria-label="{{ __('Download') }}"
                                                    class="inline-flex h-8 w-8 items-center justify-center rounded-md border border-gray-300 text-gray-700 transition hover:bg-gray-50"
                                                >
                                                    <x-menu-icon name="fa-solid fa-download" class="h-3.5 w-3.5" />
                                                </a>

                                                @can('delete', $disk)
                                                    <form method="POST" action="{{ route('disks.destroy', $disk) }}" onsubmit="return confirm('{{ __('Delete file?') }}')">
                                                        @csrf
                                                        @method('DELETE')
                                                        <button
                                                            type="submit"
                                                            title="{{ __('Delete') }}"
                                                            aria-label="{{ __('Delete') }}"
                                                            class="inline-flex h-8 w-8 items-center justify-center rounded-md border border-red-300 text-red-600 transition hover:bg-red-50"
                                                        >
                                                            <x-menu-icon name="fa-solid fa-trash-can" class="h-3.5 w-3.5" />
                                                        </button>
                                                    </form>
                                                @endcan
                                            </div>
                                        </td>
                                    </tr>
                                @empty
                                    <tr>
                                        <td colspan="7" class="px-4 py-8 text-center text-sm text-gray-500">{{ __('No files in disk.') }}</td>
                                    </tr>
                                @endforelse
                            </tbody>
                        </table>
                    </div>
                </div>

                <div
                    data-explorer-context-menu
                    class="fixed z-[70] hidden min-w-[13rem] rounded-md border border-slate-300 bg-white py-1 text-sm shadow-lg"
                >
                    <button type="button" data-action="open" class="flex w-full items-center gap-2 px-3 py-1.5 text-left hover:bg-slate-100">
                        <x-menu-icon name="fa-solid fa-up-right-from-square" class="h-3.5 w-3.5 text-slate-500" />
                        <span>{{ __('Open') }}</span>
                    </button>
                    <button type="button" data-action="copy" class="flex w-full items-center gap-2 px-3 py-1.5 text-left hover:bg-slate-100">
                        <x-menu-icon name="fa-solid fa-copy" class="h-3.5 w-3.5 text-slate-500" />
                        <span>{{ __('Copy') }}</span>
                    </button>
                    <button type="button" data-action="cut" class="flex w-full items-center gap-2 px-3 py-1.5 text-left hover:bg-slate-100">
                        <x-menu-icon name="fa-solid fa-scissors" class="h-3.5 w-3.5 text-slate-500" />
                        <span>{{ __('Cut') }}</span>
                    </button>
                    <button type="button" data-action="paste" class="flex w-full items-center gap-2 px-3 py-1.5 text-left hover:bg-slate-100">
                        <x-menu-icon name="fa-solid fa-paste" class="h-3.5 w-3.5 text-slate-500" />
                        <span>{{ __('Paste') }}</span>
                    </button>
                    <button type="button" data-action="copy-link" class="flex w-full items-center gap-2 px-3 py-1.5 text-left hover:bg-slate-100">
                        <x-menu-icon name="fa-solid fa-link" class="h-3.5 w-3.5 text-slate-500" />
                        <span>{{ __('Copy link') }}</span>
                    </button>
                    <button type="button" data-action="new-folder" class="flex w-full items-center gap-2 px-3 py-1.5 text-left hover:bg-slate-100">
                        <x-menu-icon name="fa-solid fa-folder-plus" class="h-3.5 w-3.5 text-slate-500" />
                        <span>{{ __('Create catalog') }}</span>
                    </button>
                    <button type="button" data-action="delete" class="flex w-full items-center gap-2 px-3 py-1.5 text-left text-red-600 hover:bg-red-50">
                        <x-menu-icon name="fa-solid fa-trash-can" class="h-3.5 w-3.5" />
                        <span>{{ __('Delete') }}</span>
                    </button>
                </div>
            </section>
        </div>
    </div>
</x-app-layout>

@if (($availableFolders ?? collect())->isNotEmpty())
    <datalist id="disk-folder-options">
        @foreach ($availableFolders as $folderOption)
            <option value="{{ $folderOption }}"></option>
        @endforeach
    </datalist>
@endif

@once
    <script>
        document.addEventListener('DOMContentLoaded', () => {
            const copyToClipboard = async (value) => {
                if (window.navigator && window.navigator.clipboard && typeof window.navigator.clipboard.writeText === 'function') {
                    await window.navigator.clipboard.writeText(value);
                    return;
                }

                const textarea = document.createElement('textarea');
                textarea.value = value;
                textarea.setAttribute('readonly', 'readonly');
                textarea.style.position = 'absolute';
                textarea.style.left = '-9999px';
                document.body.appendChild(textarea);
                textarea.select();
                document.execCommand('copy');
                document.body.removeChild(textarea);
            };

            const initCopyLinkButtons = () => {
                const buttons = document.querySelectorAll('[data-disk-copy-link]');
                buttons.forEach((button) => {
                    if (!(button instanceof HTMLButtonElement)) {
                        return;
                    }

                    button.addEventListener('click', async () => {
                        const url = button.dataset.copyUrl || '';
                        if (url === '') {
                            return;
                        }

                        const defaultLabel = button.dataset.labelDefault || 'Copy link';
                        const copiedLabel = button.dataset.labelCopied || 'Copied';
                        const copyLabel = button.querySelector('[data-copy-label]');
                        try {
                            await copyToClipboard(url);
                            if (copyLabel instanceof HTMLElement) {
                                copyLabel.textContent = copiedLabel;
                            }
                            button.setAttribute('title', copiedLabel);
                            button.setAttribute('aria-label', copiedLabel);
                            button.classList.add('border-emerald-300', 'text-emerald-700', 'bg-emerald-50');
                            button.classList.remove('border-sky-300', 'text-sky-700');
                            window.setTimeout(() => {
                                if (copyLabel instanceof HTMLElement) {
                                    copyLabel.textContent = defaultLabel;
                                }
                                button.setAttribute('title', defaultLabel);
                                button.setAttribute('aria-label', defaultLabel);
                                button.classList.remove('border-emerald-300', 'text-emerald-700', 'bg-emerald-50');
                                button.classList.add('border-sky-300', 'text-sky-700');
                            }, 1600);
                        } catch (error) {
                            if (copyLabel instanceof HTMLElement) {
                                copyLabel.textContent = defaultLabel;
                            }
                            button.setAttribute('title', defaultLabel);
                            button.setAttribute('aria-label', defaultLabel);
                        }
                    });
                });
            };

            const initUploadDropzone = () => {
                const dropzone = document.querySelector('[data-disk-dropzone]');
                const fileInput = document.querySelector('[data-disk-file-input]');
                const selectedFileNode = document.querySelector('[data-disk-selected-file]');

                if (!(dropzone instanceof HTMLElement) || !(fileInput instanceof HTMLInputElement)) {
                    return;
                }

                const updateSelectedFileText = () => {
                    const selectedFile = fileInput.files && fileInput.files.length > 0
                        ? fileInput.files[0]
                        : null;

                    if (!(selectedFileNode instanceof HTMLElement)) {
                        return;
                    }

                    if (!selectedFile) {
                        selectedFileNode.textContent = '';
                        selectedFileNode.classList.add('hidden');
                        return;
                    }

                    selectedFileNode.textContent = `Selected file: ${selectedFile.name}`;
                    selectedFileNode.classList.remove('hidden');
                };

                const selectFirstFile = (files) => {
                    if (!files || files.length === 0) {
                        return;
                    }

                    const firstFile = files[0];
                    if (!firstFile) {
                        return;
                    }

                    if (window.DataTransfer) {
                        const transfer = new DataTransfer();
                        transfer.items.add(firstFile);
                        fileInput.files = transfer.files;
                    } else {
                        fileInput.files = files;
                    }

                    fileInput.dispatchEvent(new Event('change', { bubbles: true }));
                };

                dropzone.addEventListener('click', () => {
                    fileInput.click();
                });

                dropzone.addEventListener('keydown', (event) => {
                    if (!(event instanceof KeyboardEvent)) {
                        return;
                    }

                    if (event.key !== 'Enter' && event.key !== ' ') {
                        return;
                    }

                    event.preventDefault();
                    fileInput.click();
                });

                ['dragenter', 'dragover'].forEach((eventName) => {
                    dropzone.addEventListener(eventName, (event) => {
                        event.preventDefault();
                        dropzone.classList.add('border-indigo-500', 'bg-indigo-50');
                    });
                });

                ['dragleave', 'dragend', 'drop'].forEach((eventName) => {
                    dropzone.addEventListener(eventName, () => {
                        dropzone.classList.remove('border-indigo-500', 'bg-indigo-50');
                    });
                });

                dropzone.addEventListener('drop', (event) => {
                    event.preventDefault();

                    const transfer = event.dataTransfer;
                    if (!transfer || !transfer.files || transfer.files.length === 0) {
                        return;
                    }

                    selectFirstFile(transfer.files);
                });

                fileInput.addEventListener('change', updateSelectedFileText);
                updateSelectedFileText();
            };

            const initExplorer = () => {
                const explorer = document.querySelector('[data-disk-explorer]');
                if (!(explorer instanceof HTMLElement)) {
                    return;
                }

                const contextMenu = explorer.querySelector('[data-explorer-context-menu]');
                if (!(contextMenu instanceof HTMLElement)) {
                    return;
                }

                const csrfToken = document.querySelector('meta[name=csrf-token]')?.getAttribute('content') ?? '';
                const folderCreateUrl = explorer.dataset.routeFolderCreate || '';
                const folderDeleteUrl = explorer.dataset.routeFolderDelete || '';
                const folderMoveUrl = explorer.dataset.routeFolderMove || '';
                const folderCopyUrl = explorer.dataset.routeFolderCopy || '';
                const fileMoveTemplate = explorer.dataset.routeFileMoveTemplate || '';
                const fileCopyTemplate = explorer.dataset.routeFileCopyTemplate || '';
                const fileDeleteTemplate = explorer.dataset.routeFileDeleteTemplate || '';
                const fileArea = explorer.querySelector('[data-explorer-file-area]');
                const newFolderButton = explorer.querySelector('[data-explorer-new-folder]');
                const createForm = explorer.querySelector('[data-explorer-create-form]');
                const createNameInput = explorer.querySelector('[data-explorer-create-name]');
                const createTargetNode = explorer.querySelector('[data-explorer-create-target]');
                const createCancelButton = explorer.querySelector('[data-explorer-create-cancel]');
                const statusNode = explorer.querySelector('[data-explorer-status]');
                const jumpForm = explorer.querySelector('[data-explorer-jump-form]');
                const jumpPathInput = explorer.querySelector('[data-explorer-path-input]');
                const jumpUpButton = explorer.querySelector('[data-explorer-up]');
                const folderNodes = Array.from(explorer.querySelectorAll('[data-folder-node]'));
                const fileRows = Array.from(explorer.querySelectorAll('[data-file-row]'));

                const state = {
                    clipboard: null,
                    context: null,
                    busy: false,
                    currentFolder: String(explorer.dataset.currentFolder || ''),
                    currentOwnerId: Number(explorer.dataset.currentOwnerId || 0),
                    createTargetFolder: String(explorer.dataset.currentFolder || ''),
                    createTargetOwnerId: Number(explorer.dataset.currentOwnerId || 0),
                };

                const actionButtons = new Map(
                    Array.from(contextMenu.querySelectorAll('[data-action]'))
                        .map((button) => [String(button.dataset.action || ''), button])
                );

                const buildFileRoute = (template, fileId) => template.replace('__DISK__', String(fileId));

                const requestJson = async (url, method, payload = null) => {
                    const response = await fetch(url, {
                        method,
                        headers: {
                            'X-CSRF-TOKEN': csrfToken,
                            'Accept': 'application/json',
                            ...(payload ? { 'Content-Type': 'application/json' } : {}),
                        },
                        body: payload ? JSON.stringify(payload) : null,
                    });

                    if (!response.ok) {
                        let errorMessage = `HTTP ${response.status}`;
                        try {
                            const data = await response.json();
                            if (typeof data?.message === 'string' && data.message.trim() !== '') {
                                errorMessage = data.message;
                            } else if (data?.errors && typeof data.errors === 'object') {
                                const firstErrors = Object.values(data.errors).find((messages) => Array.isArray(messages) && messages.length > 0);
                                if (Array.isArray(firstErrors) && typeof firstErrors[0] === 'string') {
                                    errorMessage = firstErrors[0];
                                }
                            }
                        } catch (e) {
                            // ignore JSON parsing errors and keep generic text
                        }

                        throw new Error(errorMessage);
                    }

                    if (response.status === 204) {
                        return null;
                    }

                    return response.json();
                };

                const setStatus = (message, tone = 'info') => {
                    if (!(statusNode instanceof HTMLElement)) {
                        return;
                    }

                    const normalized = String(message || '').trim();
                    if (normalized === '') {
                        statusNode.textContent = '';
                        statusNode.classList.add('hidden');
                        statusNode.classList.remove(
                            'border-slate-200', 'bg-slate-50', 'text-slate-700',
                            'border-emerald-200', 'bg-emerald-50', 'text-emerald-700',
                            'border-rose-200', 'bg-rose-50', 'text-rose-700'
                        );
                        return;
                    }

                    statusNode.classList.remove('hidden');
                    statusNode.textContent = normalized;
                    statusNode.classList.remove(
                        'border-slate-200', 'bg-slate-50', 'text-slate-700',
                        'border-emerald-200', 'bg-emerald-50', 'text-emerald-700',
                        'border-rose-200', 'bg-rose-50', 'text-rose-700'
                    );

                    if (tone === 'success') {
                        statusNode.classList.add('border-emerald-200', 'bg-emerald-50', 'text-emerald-700');
                        return;
                    }

                    if (tone === 'error') {
                        statusNode.classList.add('border-rose-200', 'bg-rose-50', 'text-rose-700');
                        return;
                    }

                    statusNode.classList.add('border-slate-200', 'bg-slate-50', 'text-slate-700');
                };

                const normalizeFolderPathInput = (value) => {
                    const normalized = String(value || '')
                        .replace(/\\/g, '/')
                        .split('/')
                        .map((part) => part.trim())
                        .filter((part) => part !== '')
                        .join('/');

                    return normalized;
                };

                const targetFolderLabel = (folderPath) => {
                    const normalized = String(folderPath || '').trim();
                    if (normalized === '') {
                        return @js(__('Create in root'));
                    }

                    return `${@js(__('Create in'))} ${normalized}`;
                };

                const hideCreateForm = () => {
                    if (!(createForm instanceof HTMLElement)) {
                        return;
                    }

                    createForm.classList.add('hidden');
                    if (createNameInput instanceof HTMLInputElement) {
                        createNameInput.value = '';
                    }
                };

                const showCreateForm = (parentFolder, ownerId) => {
                    if (!(createForm instanceof HTMLElement) || !(createNameInput instanceof HTMLInputElement)) {
                        return;
                    }

                    state.createTargetFolder = String(parentFolder || '');
                    state.createTargetOwnerId = Number(ownerId || 0);

                    if (createTargetNode instanceof HTMLElement) {
                        createTargetNode.textContent = targetFolderLabel(state.createTargetFolder);
                    }

                    createForm.classList.remove('hidden');
                    setStatus('');

                    window.setTimeout(() => {
                        createNameInput.focus();
                        createNameInput.select();
                    }, 0);
                };

                const hideContextMenu = () => {
                    contextMenu.classList.add('hidden');
                    state.context = null;
                };

                const setActionVisible = (action, visible) => {
                    const button = actionButtons.get(action);
                    if (!(button instanceof HTMLElement)) {
                        return;
                    }

                    button.classList.toggle('hidden', !visible);
                };

                const renderContextMenu = () => {
                    const context = state.context;
                    const hasClipboard = !!state.clipboard;

                    setActionVisible('open', context?.type === 'file' || context?.type === 'folder');
                    setActionVisible('copy', context?.type === 'file' || context?.type === 'folder');
                    setActionVisible('cut', context?.type === 'file' || context?.type === 'folder');
                    setActionVisible('paste', (context?.type === 'folder' || context?.type === 'canvas') && hasClipboard);
                    setActionVisible('copy-link', context?.type === 'file');
                    setActionVisible('new-folder', Boolean(createForm) && (context?.type === 'folder' || context?.type === 'canvas'));
                    setActionVisible('delete', context?.type === 'file' || (context?.type === 'folder' && context.path !== ''));
                };

                const showContextMenu = (event, context) => {
                    event.preventDefault();
                    state.context = context;
                    renderContextMenu();
                    contextMenu.classList.remove('hidden');

                    const menuRect = contextMenu.getBoundingClientRect();
                    const viewportWidth = window.innerWidth;
                    const viewportHeight = window.innerHeight;

                    let left = event.clientX;
                    let top = event.clientY;

                    if (left + menuRect.width > viewportWidth - 8) {
                        left = Math.max(8, viewportWidth - menuRect.width - 8);
                    }

                    if (top + menuRect.height > viewportHeight - 8) {
                        top = Math.max(8, viewportHeight - menuRect.height - 8);
                    }

                    contextMenu.style.left = `${left}px`;
                    contextMenu.style.top = `${top}px`;
                };

                const reloadExplorer = (nextFolder = state.currentFolder, nextOwnerId = state.currentOwnerId) => {
                    const url = new URL(window.location.href);

                    if (nextFolder && nextFolder !== '') {
                        url.searchParams.set('folder', nextFolder);
                    } else {
                        url.searchParams.delete('folder');
                    }

                    if (nextOwnerId > 0) {
                        url.searchParams.set('owner_id', String(nextOwnerId));
                    } else {
                        url.searchParams.delete('owner_id');
                    }

                    window.location.assign(url.toString());
                };

                const performPaste = async (targetFolder, targetOwnerId) => {
                    if (!state.clipboard || state.busy) {
                        return;
                    }

                    const clipboard = state.clipboard;
                    state.busy = true;
                    try {
                        if (clipboard.type === 'file') {
                            const route = clipboard.cut ? fileMoveTemplate : fileCopyTemplate;
                            const url = buildFileRoute(route, clipboard.id);
                            await requestJson(url, clipboard.cut ? 'PATCH' : 'POST', {
                                destination_folder: targetFolder || '',
                            });
                        } else if (clipboard.type === 'folder') {
                            const url = clipboard.cut ? folderMoveUrl : folderCopyUrl;
                            await requestJson(url, clipboard.cut ? 'PATCH' : 'POST', {
                                source_folder: clipboard.path,
                                destination_folder: targetFolder || '',
                                owner_id: clipboard.ownerId > 0 ? clipboard.ownerId : (targetOwnerId > 0 ? targetOwnerId : null),
                            });
                        }

                        if (clipboard.cut) {
                            state.clipboard = null;
                        }

                        setStatus(@js(__('Operation completed.')), 'success');
                        reloadExplorer(targetFolder || state.currentFolder, targetOwnerId || state.currentOwnerId);
                    } catch (error) {
                        setStatus(error instanceof Error ? error.message : @js(__('Operation failed.')), 'error');
                    } finally {
                        state.busy = false;
                    }
                };

                const executeAction = async (action) => {
                    const context = state.context;
                    hideContextMenu();

                    if (!context || state.busy) {
                        return;
                    }

                    if (action === 'open') {
                        if (typeof context.url === 'string' && context.url !== '') {
                            window.location.assign(context.url);
                        }

                        return;
                    }

                    if (action === 'copy') {
                        if (context.type === 'file') {
                            state.clipboard = { type: 'file', id: context.id, cut: false };
                        } else if (context.type === 'folder') {
                            state.clipboard = { type: 'folder', path: context.path, ownerId: context.ownerId, cut: false };
                        }

                        return;
                    }

                    if (action === 'cut') {
                        if (context.type === 'file') {
                            state.clipboard = { type: 'file', id: context.id, cut: true };
                        } else if (context.type === 'folder' && context.path !== '') {
                            state.clipboard = { type: 'folder', path: context.path, ownerId: context.ownerId, cut: true };
                        }

                        return;
                    }

                    if (action === 'copy-link' && context.type === 'file') {
                        if (typeof context.previewUrl === 'string' && context.previewUrl !== '') {
                            await copyToClipboard(context.previewUrl);
                            setStatus(@js(__('Link copied.')), 'success');
                        }

                        return;
                    }

                    if (action === 'new-folder') {
                        const parentFolder = context.type === 'folder'
                            ? context.path
                            : (state.currentFolder || '');
                        const ownerId = context.type === 'folder'
                            ? context.ownerId
                            : state.currentOwnerId;
                        showCreateForm(parentFolder, ownerId);

                        return;
                    }

                    if (action === 'paste') {
                        const targetFolder = context.type === 'folder'
                            ? context.path
                            : (state.currentFolder || '');
                        const targetOwnerId = context.type === 'folder'
                            ? context.ownerId
                            : state.currentOwnerId;

                        await performPaste(targetFolder, targetOwnerId);

                        return;
                    }

                    if (action === 'delete') {
                        if (!window.confirm(@js(__('Delete selected item?')))) {
                            return;
                        }

                        state.busy = true;
                        try {
                            if (context.type === 'file') {
                                await requestJson(buildFileRoute(fileDeleteTemplate, context.id), 'DELETE');
                                setStatus(@js(__('File deleted.')), 'success');
                                reloadExplorer(state.currentFolder, state.currentOwnerId);
                                return;
                            }

                            if (context.type === 'folder' && context.path !== '') {
                                await requestJson(folderDeleteUrl, 'DELETE', {
                                    folder: context.path,
                                    owner_id: context.ownerId > 0 ? context.ownerId : null,
                                });

                                const nextFolder = state.currentFolder === context.path ? '' : state.currentFolder;
                                const nextOwner = context.ownerId > 0 ? context.ownerId : state.currentOwnerId;
                                setStatus(@js(__('Folder deleted.')), 'success');
                                reloadExplorer(nextFolder, nextOwner);
                            }
                        } catch (error) {
                            setStatus(error instanceof Error ? error.message : @js(__('Operation failed.')), 'error');
                        } finally {
                            state.busy = false;
                        }
                    }
                };

                folderNodes.forEach((node) => {
                    if (!(node instanceof HTMLElement)) {
                        return;
                    }

                    const folderPath = String(node.dataset.folderPath || '');
                    const folderOwnerId = Number(node.dataset.folderOwnerId || 0);
                    const folderUrl = node instanceof HTMLAnchorElement ? node.href : '';

                    node.addEventListener('contextmenu', (event) => {
                        showContextMenu(event, {
                            type: 'folder',
                            path: folderPath,
                            ownerId: folderOwnerId,
                            url: folderUrl,
                        });
                    });

                    node.addEventListener('dragstart', (event) => {
                        if (folderPath === '') {
                            event.preventDefault();
                            return;
                        }

                        const payload = {
                            type: 'folder',
                            path: folderPath,
                            ownerId: folderOwnerId,
                        };

                        event.dataTransfer?.setData('application/json', JSON.stringify(payload));
                        event.dataTransfer?.setData('text/plain', JSON.stringify(payload));
                        node.classList.add('opacity-60');
                    });

                    node.addEventListener('dragend', () => {
                        node.classList.remove('opacity-60');
                    });

                    node.addEventListener('dragover', (event) => {
                        event.preventDefault();
                        node.classList.add('ring-2', 'ring-indigo-300');
                    });

                    node.addEventListener('dragleave', () => {
                        node.classList.remove('ring-2', 'ring-indigo-300');
                    });

                    node.addEventListener('drop', async (event) => {
                        event.preventDefault();
                        node.classList.remove('ring-2', 'ring-indigo-300');

                        if (state.busy) {
                            return;
                        }

                        const payloadRaw = event.dataTransfer?.getData('application/json') || event.dataTransfer?.getData('text/plain') || '';
                        if (payloadRaw === '') {
                            return;
                        }

                        let payload;
                        try {
                            payload = JSON.parse(payloadRaw);
                        } catch (e) {
                            return;
                        }

                        if (!payload || typeof payload !== 'object') {
                            return;
                        }

                        state.busy = true;
                        try {
                            if (payload.type === 'file' && Number(payload.id || 0) > 0) {
                                await requestJson(buildFileRoute(fileMoveTemplate, Number(payload.id)), 'PATCH', {
                                    destination_folder: folderPath,
                                });
                            } else if (payload.type === 'folder' && typeof payload.path === 'string' && payload.path !== '') {
                                await requestJson(folderMoveUrl, 'PATCH', {
                                    source_folder: payload.path,
                                    destination_folder: folderPath,
                                    owner_id: Number(payload.ownerId || 0) > 0 ? Number(payload.ownerId) : (folderOwnerId > 0 ? folderOwnerId : null),
                                });
                            }

                            reloadExplorer(folderPath, folderOwnerId || state.currentOwnerId);
                        } catch (error) {
                            setStatus(error instanceof Error ? error.message : @js(__('Operation failed.')), 'error');
                        } finally {
                            state.busy = false;
                        }
                    });
                });

                fileRows.forEach((row) => {
                    if (!(row instanceof HTMLElement)) {
                        return;
                    }

                    const fileId = Number(row.dataset.fileId || 0);
                    const fileOwnerId = Number(row.dataset.fileOwnerId || 0);
                    const fileFolder = String(row.dataset.fileFolder || '');
                    const previewUrl = String(row.dataset.previewUrl || '');

                    row.addEventListener('contextmenu', (event) => {
                        showContextMenu(event, {
                            type: 'file',
                            id: fileId,
                            ownerId: fileOwnerId,
                            folder: fileFolder,
                            previewUrl,
                            url: previewUrl,
                        });
                    });

                    row.addEventListener('dragstart', (event) => {
                        const payload = {
                            type: 'file',
                            id: fileId,
                            ownerId: fileOwnerId,
                        };

                        event.dataTransfer?.setData('application/json', JSON.stringify(payload));
                        event.dataTransfer?.setData('text/plain', JSON.stringify(payload));
                        row.classList.add('opacity-60');
                    });

                    row.addEventListener('dragend', () => {
                        row.classList.remove('opacity-60');
                    });
                });

                if (fileArea instanceof HTMLElement) {
                    fileArea.addEventListener('contextmenu', (event) => {
                        const target = event.target;
                        if (target instanceof HTMLElement && target.closest('[data-file-row]')) {
                            return;
                        }

                        showContextMenu(event, {
                            type: 'canvas',
                            path: state.currentFolder || '',
                            ownerId: state.currentOwnerId,
                        });
                    });

                    fileArea.addEventListener('dragover', (event) => {
                        event.preventDefault();
                        fileArea.classList.add('bg-indigo-50/40');
                    });

                    fileArea.addEventListener('dragleave', () => {
                        fileArea.classList.remove('bg-indigo-50/40');
                    });

                    fileArea.addEventListener('drop', async (event) => {
                        event.preventDefault();
                        fileArea.classList.remove('bg-indigo-50/40');

                        if (state.busy) {
                            return;
                        }

                        const payloadRaw = event.dataTransfer?.getData('application/json') || event.dataTransfer?.getData('text/plain') || '';
                        if (payloadRaw === '') {
                            return;
                        }

                        let payload;
                        try {
                            payload = JSON.parse(payloadRaw);
                        } catch (e) {
                            return;
                        }

                        state.busy = true;
                        try {
                            if (payload.type === 'file' && Number(payload.id || 0) > 0) {
                                await requestJson(buildFileRoute(fileMoveTemplate, Number(payload.id)), 'PATCH', {
                                    destination_folder: state.currentFolder || '',
                                });
                            } else if (payload.type === 'folder' && typeof payload.path === 'string' && payload.path !== '') {
                                await requestJson(folderMoveUrl, 'PATCH', {
                                    source_folder: payload.path,
                                    destination_folder: state.currentFolder || '',
                                    owner_id: Number(payload.ownerId || 0) > 0 ? Number(payload.ownerId) : (state.currentOwnerId > 0 ? state.currentOwnerId : null),
                                });
                            }

                            reloadExplorer(state.currentFolder, state.currentOwnerId);
                        } catch (error) {
                            setStatus(error instanceof Error ? error.message : @js(__('Operation failed.')), 'error');
                        } finally {
                            state.busy = false;
                        }
                    });
                }

                if (newFolderButton instanceof HTMLElement) {
                    newFolderButton.addEventListener('click', () => {
                        showCreateForm(state.currentFolder || '', state.currentOwnerId);
                    });
                }

                if (createCancelButton instanceof HTMLElement) {
                    createCancelButton.addEventListener('click', () => {
                        hideCreateForm();
                        setStatus('');
                    });
                }

                if (createForm instanceof HTMLFormElement) {
                    createForm.addEventListener('submit', async (event) => {
                        event.preventDefault();

                        if (!(createNameInput instanceof HTMLInputElement) || state.busy) {
                            return;
                        }

                        const name = createNameInput.value.trim();
                        if (name === '') {
                            setStatus(@js(__('Catalog name is required.')), 'error');
                            createNameInput.focus();
                            return;
                        }

                        state.busy = true;
                        try {
                            const response = await requestJson(folderCreateUrl, 'POST', {
                                name,
                                parent_folder: state.createTargetFolder || '',
                                owner_id: state.createTargetOwnerId > 0 ? state.createTargetOwnerId : null,
                            });

                            const createdPath = typeof response?.folder?.path === 'string'
                                ? response.folder.path
                                : '';
                            setStatus(@js(__('Catalog created.')), 'success');
                            hideCreateForm();
                            reloadExplorer(createdPath, state.createTargetOwnerId || state.currentOwnerId);
                        } catch (error) {
                            setStatus(error instanceof Error ? error.message : @js(__('Operation failed.')), 'error');
                        } finally {
                            state.busy = false;
                        }
                    });
                }

                if (jumpForm instanceof HTMLFormElement && jumpPathInput instanceof HTMLInputElement) {
                    jumpForm.addEventListener('submit', (event) => {
                        event.preventDefault();
                        const nextPath = normalizeFolderPathInput(jumpPathInput.value);
                        reloadExplorer(nextPath, state.currentOwnerId);
                    });
                }

                if (jumpUpButton instanceof HTMLElement) {
                    jumpUpButton.addEventListener('click', () => {
                        if (state.currentFolder === '') {
                            reloadExplorer('', state.currentOwnerId);
                            return;
                        }

                        const parts = state.currentFolder.split('/').filter((part) => part !== '');
                        parts.pop();
                        reloadExplorer(parts.join('/'), state.currentOwnerId);
                    });
                }

                contextMenu.addEventListener('click', async (event) => {
                    const button = event.target instanceof HTMLElement
                        ? event.target.closest('[data-action]')
                        : null;
                    if (!(button instanceof HTMLElement)) {
                        return;
                    }

                    const action = String(button.dataset.action || '');
                    if (action === '') {
                        return;
                    }

                    await executeAction(action);
                });

                document.addEventListener('click', (event) => {
                    if (!(event.target instanceof Node)) {
                        hideContextMenu();
                        return;
                    }

                    if (!contextMenu.contains(event.target)) {
                        hideContextMenu();
                    }
                });

                document.addEventListener('keydown', (event) => {
                    if (event.key === 'Escape') {
                        hideContextMenu();
                        hideCreateForm();
                    }
                });
            };

            initCopyLinkButtons();
            initUploadDropzone();
            initExplorer();
        });
    </script>
@endonce
