{% extends 'base.html' %}
{% load i18n %}
{% load static %}

{% block extra_css %}
{% endblock %}

{% block content %}
<!-- Single Alpine scope wraps the entire page + HUD -->
<div x-data="fileManager()"
     @open-expiry.window="openExpiry($event.detail)"
     @copy-link.window="copyAndToast($event.detail.url)">

<!-- Hidden file input -->
<input type="file" id="globalFileInput" multiple class="hidden">

<!-- Full-page drag overlay -->
<div id="dragOverlay"
     class="fixed inset-0 z-40 bg-red-50/80 border-4 border-dashed border-red-400 flex items-center justify-center pointer-events-none opacity-0 transition-opacity duration-150">
    <div class="text-center">
        <svg class="w-16 h-16 mx-auto text-red-400 mb-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"
                  d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12"/>
        </svg>
        <p class="text-xl font-semibold text-red-600">{% trans "Drop files to upload" %}</p>
    </div>
</div>

<!-- Main content -->
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-6">

    <!-- Header -->
    <div class="flex justify-between items-center mb-6">
        <h1 class="text-2xl font-bold text-gray-900">{% trans "Files" %}</h1>
        <button @click="openPicker()"
                class="inline-flex items-center px-4 py-2 bg-red-600 text-white text-sm font-medium rounded-md hover:bg-red-700 transition-colors">
            <svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
                      d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-8l-4-4m0 0L8 8m4-4v12"/>
            </svg>
            {% trans "Upload Files" %}
        </button>
    </div>

    <!-- Files Table -->
    <div class="bg-white shadow-md rounded-lg overflow-hidden">
        <div class="bg-gray-50 border-b border-gray-200 px-4 py-3">
            <h2 class="text-sm font-semibold text-gray-700">
                {% trans "All Files" %} <span class="text-gray-400 font-normal">({{ files.count }})</span>
            </h2>
        </div>

        {% if files %}
        <div class="overflow-x-auto">
            <table class="min-w-full divide-y divide-gray-200 text-sm">
                <thead class="bg-gray-50">
                    <tr>
                        <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">{% trans "Name" %}</th>
                        <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider hidden md:table-cell">{% trans "Type" %}</th>
                        <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">{% trans "Size" %}</th>
                        <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider hidden sm:table-cell">{% trans "Uploaded" %}</th>
                        <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">{% trans "Public" %}</th>
                        <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider hidden sm:table-cell">{% trans "Downloads" %}</th>
                        <th class="px-4 py-3 text-right text-xs font-medium text-gray-500 uppercase tracking-wider">{% trans "Actions" %}</th>
                    </tr>
                </thead>
                <tbody class="bg-white divide-y divide-gray-100">
                    {% for file in files %}
                    <tr class="hover:bg-gray-50"
                        x-data="fileRow('{{ file.pk }}', {{ file.is_public|lower }}, '{{ file.expires_at|date:'c'|default:'' }}', '{{ file.public_url }}')">
                        <!-- Name -->
                        <td class="px-4 py-3">
                            <a href="{{ file.download_url }}"
                               class="font-medium text-blue-600 hover:text-blue-800 hover:underline flex items-center max-w-xs"
                               @click.prevent="window.dispatchEvent(new CustomEvent('open-preview', {detail: {name: '{{ file.name|escapejs }}', mimeType: '{{ file.mime_type }}', url: '{{ file.download_url }}'}}))">
                                <svg class="w-4 h-4 mr-2 text-gray-400 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                                    {% if file.is_image %}
                                    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"/>
                                    {% else %}
                                    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
                                    {% endif %}
                                </svg>
                                <span class="truncate">{{ file.name }}</span>
                            </a>
                        </td>
                        <!-- Type -->
                        <td class="px-4 py-3 text-gray-500 hidden md:table-cell">{{ file.mime_type|truncatechars:30 }}</td>
                        <!-- Size -->
                        <td class="px-4 py-3 text-gray-600 whitespace-nowrap">{{ file.formatted_size }}</td>
                        <!-- Uploaded -->
                        <td class="px-4 py-3 text-gray-500 whitespace-nowrap hidden sm:table-cell">{{ file.created_at|date:"Y-m-d H:i" }}</td>
                        <!-- Public -->
                        <td class="px-4 py-3">
                            <div class="flex flex-col space-y-1">
                                <span x-show="isPublic"
                                      class="inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-green-100 text-green-800 cursor-pointer w-fit"
                                      @click="togglePublic()"
                                      title="{% trans 'Click to make private' %}">
                                    ● {% trans "Public" %}
                                </span>
                                <span x-show="!isPublic"
                                      class="inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-gray-100 text-gray-600 cursor-pointer w-fit"
                                      @click="togglePublic()"
                                      title="{% trans 'Click to make public' %}">
                                    ○ {% trans "Private" %}
                                </span>
                                <span x-show="isPublic && expiresAt"
                                      :class="isExpired ? 'text-red-500' : 'text-gray-400'"
                                      class="text-xs cursor-pointer"
                                      @click="window.dispatchEvent(new CustomEvent('open-expiry', {detail: {pk, expiresAt}}))"
                                      x-text="isExpired ? '⚠ Expired' : '⏱ ' + formatExpiry(expiresAt)">
                                </span>
                                <span x-show="isPublic && !expiresAt"
                                      class="text-xs text-gray-400 cursor-pointer"
                                      @click="window.dispatchEvent(new CustomEvent('open-expiry', {detail: {pk, expiresAt}}))">
                                    {% trans "No expiry" %}
                                </span>
                                <span x-show="isPublic" class="text-xs">
                                    <button @click="copyPublicUrl()"
                                            class="text-blue-500 hover:text-blue-700 flex items-center">
                                        <svg class="w-3 h-3 mr-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                                            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"/>
                                        </svg>
                                        {% trans "Copy link" %}
                                    </button>
                                </span>
                            </div>
                        </td>
                        <!-- Downloads -->
                        <td class="px-4 py-3 text-gray-600 hidden sm:table-cell">{{ file.download_count }}</td>
                        <!-- Actions -->
                        <td class="px-4 py-3 text-right relative">
                            <div class="flex items-center justify-end space-x-1">
                                <a href="{{ file.download_url }}"
                                   {% if file.is_image %}target="_blank"{% endif %}
                                   class="p-1.5 text-gray-500 hover:text-blue-600 hover:bg-blue-50 rounded"
                                   title="{% trans 'Download / View' %}">
                                    <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                                        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"/>
                                    </svg>
                                </a>
                                <button x-show="isPublic"
                                        @click="window.dispatchEvent(new CustomEvent('open-expiry', {detail: {pk, expiresAt}}))"
                                        class="p-1.5 text-gray-500 hover:text-yellow-600 hover:bg-yellow-50 rounded"
                                        title="{% trans 'Set expiry' %}">
                                    <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                                        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/>
                                    </svg>
                                </button>
                                <form method="post" action="{% url 'file-delete' file.pk %}"
                                      @submit.prevent="if(confirm('{% trans 'Delete this file?' %}')) $el.submit()">
                                    {% csrf_token %}
                                    <button type="submit"
                                            class="p-1.5 text-gray-500 hover:text-red-600 hover:bg-red-50 rounded"
                                            title="{% trans 'Delete' %}">
                                        <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                                            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"/>
                                        </svg>
                                    </button>
                                </form>
                            </div>

                        </td>
                    </tr>
                    {% endfor %}
                </tbody>
            </table>
        </div>
        {% else %}
        <div class="py-16 text-center text-gray-400">
            <svg class="w-12 h-12 mx-auto mb-4 text-gray-300" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"
                      d="M7 21h10a2 2 0 002-2V9.414a1 1 0 00-.293-.707l-5.414-5.414A1 1 0 0012.586 3H7a2 2 0 00-2 2v14a2 2 0 002 2z"/>
            </svg>
            <p class="text-sm font-medium">{% trans "No files yet" %}</p>
            <p class="text-xs mt-1">{% trans "Drag files anywhere on this page, or click Upload Files above." %}</p>
        </div>
        {% endif %}
    </div>

</div><!-- /main content -->

<!-- ── Toast notification ──────────────────────────────────────── -->
<div x-show="toastVisible"
     x-transition:enter="transition ease-out duration-200"
     x-transition:enter-start="opacity-0 -translate-y-1"
     x-transition:enter-end="opacity-100 translate-y-0"
     x-transition:leave="transition ease-in duration-150"
     x-transition:leave-start="opacity-100 translate-y-0"
     x-transition:leave-end="opacity-0 -translate-y-1"
     style="position:fixed;top:5rem;right:1.5rem;z-index:9999;pointer-events:none;background:#111827;color:#fff;font-size:.875rem;padding:.625rem 1rem;border-radius:.5rem;box-shadow:0 10px 25px rgba(0,0,0,.4);display:flex;align-items:center;gap:.5rem;"
    <svg style="width:1rem;height:1rem;color:#4ade80;flex-shrink:0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
    </svg>
    <span x-text="toastMsg"></span>
</div>

<!-- ── Global Expiry Modal ─────────────────────────────────────── -->
<div x-show="expiryModal.open"
     x-transition:enter="transition ease-out duration-150"
     x-transition:enter-start="opacity-0"
     x-transition:enter-end="opacity-100"
     x-transition:leave="transition ease-in duration-100"
     x-transition:leave-start="opacity-100"
     x-transition:leave-end="opacity-0"
     style="position:fixed;inset:0;z-index:9999"
     class="bg-black/40 flex items-center justify-center p-4"
     @click.self="expiryModal.open = false">
    <div class="bg-white rounded-xl shadow-2xl w-full max-w-sm p-6"
         x-transition:enter="transition ease-out duration-150"
         x-transition:enter-start="opacity-0 scale-95"
         x-transition:enter-end="opacity-100 scale-100">
        <div class="flex items-center justify-between mb-4">
            <h3 class="text-base font-semibold text-gray-900">{% trans "Set Expiry Date" %}</h3>
            <button @click="expiryModal.open = false"
                    class="text-gray-400 hover:text-gray-600 p-1 rounded hover:bg-gray-100">
                <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
                </svg>
            </button>
        </div>
        <p class="text-sm text-gray-500 mb-4">{% trans "Leave blank for no expiry. The public link will stop working after this date." %}</p>
        <input type="datetime-local" x-model="expiryModal.expiryInput"
               class="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-red-500 focus:border-transparent">
        <div class="flex justify-between items-center mt-5">
            <button @click="clearExpiry()"
                    class="text-sm text-red-500 hover:text-red-700 font-medium">{% trans "Clear expiry" %}</button>
            <div class="flex space-x-2">
                <button @click="expiryModal.open = false"
                        class="px-4 py-2 text-sm border border-gray-300 rounded-lg hover:bg-gray-50 transition-colors">{% trans "Cancel" %}</button>
                <button @click="saveExpiry()"
                        class="px-4 py-2 text-sm text-white bg-red-600 rounded-lg hover:bg-red-700 transition-colors">{% trans "Save" %}</button>
            </div>
        </div>
    </div>
</div>

<!-- ── Upload Progress HUD ────────────────────────────────────────
     Always rendered. Stuck to bottom-right via inline style so no
     ancestor transform can interfere with CSS position:fixed.
──────────────────────────────────────────────────────────────── -->
<div style="position:fixed;bottom:1.5rem;right:1.5rem;z-index:9999;width:20rem">
    <div class="bg-white rounded-xl shadow-2xl border border-gray-200 overflow-hidden">

        <!-- Header — always visible, click to fold/unfold -->
        <div @click="hudOpen = !hudOpen"
             class="flex items-center justify-between px-4 py-3 bg-gray-50 border-b border-gray-200 cursor-pointer select-none">
            <div class="flex items-center space-x-2">
                <!-- animated pulse dot when uploading -->
                <span x-show="uploads.some(u => u.status === 'uploading')"
                      class="w-2 h-2 rounded-full bg-blue-500 animate-pulse flex-shrink-0"></span>
                <span x-show="!uploads.some(u => u.status === 'uploading')"
                      class="w-2 h-2 rounded-full bg-gray-300 flex-shrink-0"></span>
                <span class="text-sm font-semibold text-gray-700">
                    <span x-show="uploads.some(u => u.status === 'uploading')"
                          x-text="'{% trans "Uploading" %} ' + uploads.filter(u => u.status === 'uploading').length + ' / ' + uploads.length"></span>
                    <span x-show="!uploads.some(u => u.status === 'uploading')">{% trans "Uploads" %}</span>
                </span>
            </div>
            <div class="flex items-center space-x-2">
                <button x-show="uploads.some(u => u.status === 'uploading')"
                        @click.stop="cancelAll()"
                        class="text-xs text-red-500 hover:text-red-700 font-medium px-2 py-0.5 rounded hover:bg-red-50 transition-colors">
                    {% trans "Cancel" %}
                </button>
                <!-- chevron rotates when open -->
                <svg class="w-4 h-4 text-gray-400 transition-transform duration-200"
                     :class="hudOpen ? '' : 'rotate-180'"
                     fill="none" stroke="currentColor" viewBox="0 0 24 24">
                    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
                </svg>
            </div>
        </div>

        <!-- Collapsible body -->
        <div x-show="hudOpen"
             x-transition:enter="transition ease-out duration-150"
             x-transition:enter-start="opacity-0 -translate-y-1"
             x-transition:enter-end="opacity-100 translate-y-0"
             x-transition:leave="transition ease-in duration-100"
             x-transition:leave-start="opacity-100 translate-y-0"
             x-transition:leave-end="opacity-0 -translate-y-1">

            <!-- Empty state -->
            <div x-show="uploads.length === 0"
                 class="px-4 py-5 text-center text-xs text-gray-400">
                {% trans "Drag files anywhere or click Upload Files." %}
            </div>

            <!-- File rows -->
            <div x-show="uploads.length > 0" class="max-h-60 overflow-y-auto divide-y divide-gray-100">
                <template x-for="u in uploads" :key="u.id">
                    <div class="px-4 py-3">
                        <div class="flex items-center justify-between mb-1.5">
                            <span class="text-xs font-medium text-gray-700 truncate max-w-[180px]" x-text="u.name"></span>
                            <span class="text-xs ml-2 flex-shrink-0 font-medium"
                                  :class="{
                                    'text-blue-500': u.status === 'uploading',
                                    'text-green-600': u.status === 'done',
                                    'text-red-500': u.status === 'error',
                                    'text-gray-400': u.status === 'cancelled'
                                  }"
                                  x-text="u.status === 'uploading' ? u.progress + '%' : u.status"></span>
                        </div>
                        <div class="w-full bg-gray-100 rounded-full h-1.5">
                            <div class="h-1.5 rounded-full transition-all duration-200"
                                 :class="{
                                   'bg-blue-500': u.status === 'uploading',
                                   'bg-green-500': u.status === 'done',
                                   'bg-red-400': u.status === 'error',
                                   'bg-gray-300': u.status === 'cancelled'
                                 }"
                                 :style="'width:' + u.progress + '%'"></div>
                        </div>
                    </div>
                </template>
            </div>

        </div><!-- /collapsible body -->
    </div>
</div><!-- /HUD -->

<!-- ── File Preview Modal ─────────────────────────────────────── -->
<div x-show="previewModal.open" x-cloak
     class="fixed inset-0 z-50 flex items-center justify-center bg-black/80 p-4"
     @click.self="closePreview()"
     @keydown.escape.window="closePreview()">

    <!-- Modal: auto-sizes to content, never exceeds 92vw × 92vh -->
    <div class="relative bg-white rounded-xl shadow-2xl flex flex-col overflow-hidden"
         style="max-width:min(92vw,1280px); max-height:92vh; width:max-content; min-width:300px;">

        <!-- Header -->
        <div class="flex items-center justify-between px-4 py-3 border-b border-gray-100 flex-shrink-0 w-full box-border">
            <h3 class="text-sm font-semibold text-gray-800 truncate mr-4 min-w-0" x-text="previewModal.name"></h3>
            <button @click="closePreview()" class="text-gray-400 hover:text-gray-600 flex-shrink-0 p-0.5 rounded hover:bg-gray-100">
                <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
                </svg>
            </button>
        </div>

        <!-- Body: flex-1 + min-h-0 lets it shrink properly; overflow-auto for scroll safety -->
        <div class="flex-1 min-h-0 overflow-auto flex items-center justify-center bg-gray-50 relative">

            <!-- Prev button -->
            <button x-show="fileList.length > 1"
                    @click="prevFile()"
                    class="absolute left-2 z-10 bg-black/40 hover:bg-black/60 text-white rounded-full p-2 transition-colors"
                    title="Previous (←)">
                <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"/>
                </svg>
            </button>

            <!-- Next button -->
            <button x-show="fileList.length > 1"
                    @click="nextFile()"
                    class="absolute right-2 z-10 bg-black/40 hover:bg-black/60 text-white rounded-full p-2 transition-colors"
                    title="Next (→)">
                <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
                </svg>
            </button>

            <!-- Image: respects natural dimensions, capped at viewport -->
            <template x-if="previewModal.open && previewModal.mimeType.startsWith('image/')">
                <img :src="previewModal.url" :alt="previewModal.name"
                     style="display:block; max-width:min(88vw,1200px); max-height:calc(92vh - 96px); width:auto; height:auto; object-fit:contain;">
            </template>

            <!-- Video -->
            <template x-if="previewModal.open && previewModal.mimeType.startsWith('video/')">
                <video controls
                       style="display:block; max-width:min(88vw,1200px); max-height:calc(92vh - 96px); width:auto; height:auto;"
                       :src="previewModal.url"></video>
            </template>

            <!-- Audio -->
            <template x-if="previewModal.open && previewModal.mimeType.startsWith('audio/')">
                <div class="text-center space-y-6 py-10 px-8" style="width:360px;">
                    <svg class="w-16 h-16 text-gray-300 mx-auto" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M9 19V6l12-3v13M9 19c0 1.105-1.343 2-3 2s-3-.895-3-2 1.343-2 3-2 3 .895 3 2zm12-3c0 1.105-1.343 2-3 2s-3-.895-3-2 1.343-2 3-2 3 .895 3 2zM9 10l12-3"/>
                    </svg>
                    <p class="text-sm text-gray-600 font-medium" x-text="previewModal.name"></p>
                    <audio controls class="w-full" :src="previewModal.url"></audio>
                </div>
            </template>

            <!-- Unsupported -->
            <template x-if="previewModal.open && !previewModal.mimeType.startsWith('image/') && !previewModal.mimeType.startsWith('video/') && !previewModal.mimeType.startsWith('audio/')">
                <div class="text-center space-y-4 py-12 px-10" style="width:420px;">
                    <svg class="w-16 h-16 text-gray-200 mx-auto" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
                    </svg>
                    <p class="text-base font-semibold text-gray-700">{% trans "Unfortunately, we can't preview this file." %}</p>
                    <p class="text-sm text-gray-400">{% trans "But you can click the link below to download it." %}</p>
                    <a :href="previewModal.url" :download="previewModal.name"
                       class="inline-flex items-center px-5 py-2.5 bg-blue-600 text-white text-sm font-medium rounded-lg hover:bg-blue-700 transition-colors mt-2">
                        <svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"/>
                        </svg>
                        <span x-text="previewModal.name"></span>
                    </a>
                </div>
            </template>

        </div>

        <!-- Footer -->
        <div class="px-4 py-2.5 border-t border-gray-100 flex items-center justify-between flex-shrink-0 bg-white w-full box-border">
            <div class="flex items-center gap-3">
                <span class="text-xs text-gray-400" x-text="previewModal.mimeType"></span>
                <span x-show="fileList.length > 1" class="text-xs text-gray-400"
                      x-text="(currentIndex + 1) + ' / ' + fileList.length"></span>
            </div>
            <a :href="previewModal.url" :download="previewModal.name"
               class="inline-flex items-center text-sm text-blue-600 hover:text-blue-800">
                <svg class="w-4 h-4 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"/>
                </svg>
                {% trans "Download" %}
            </a>
        </div>

    </div>
</div>

</div><!-- /Alpine scope -->

<script>
function fileManager() {
    return {
        uploads: [],
        hudOpen: false,
        toastMsg: '',
        toastVisible: false,
        _toastTimer: null,
        expiryModal: { open: false, pk: '', expiryInput: '' },
        previewModal: { open: false, name: '', mimeType: '', url: '' },
        fileList: [],
        currentIndex: -1,

        init() {
            window.addEventListener('open-preview', e => this.openPreview(e.detail));

            // Load file list for keyboard navigation
            try {
                this.fileList = JSON.parse(document.getElementById('file-list-data').textContent);
            } catch(e) { this.fileList = []; }

            // Arrow key navigation
            window.addEventListener('keydown', e => {
                if (!this.previewModal.open) return;
                if (e.key === 'ArrowRight') { e.preventDefault(); this.nextFile(); }
                else if (e.key === 'ArrowLeft') { e.preventDefault(); this.prevFile(); }
            });

            const overlay = document.getElementById('dragOverlay');
            const input = document.getElementById('globalFileInput');
            let dragCounter = 0;

            document.addEventListener('dragenter', e => {
                if (!e.dataTransfer?.types?.includes('Files')) return;
                dragCounter++;
                overlay.style.opacity = '1';
            });
            document.addEventListener('dragleave', () => {
                dragCounter = Math.max(0, dragCounter - 1);
                if (dragCounter === 0) overlay.style.opacity = '0';
            });
            document.addEventListener('dragover', e => e.preventDefault());
            document.addEventListener('drop', e => {
                e.preventDefault();
                dragCounter = 0;
                overlay.style.opacity = '0';
                const files = e.dataTransfer?.files;
                if (files?.length) this.uploadFiles(files);
            });

            input.addEventListener('change', e => {
                if (e.target.files.length) this.uploadFiles(e.target.files);
                e.target.value = '';
            });
        },

        openPicker() {
            document.getElementById('globalFileInput').click();
        },

        // ── Uploads ─────────────────────────────────────────────────
        uploadFiles(fileList) {
            this.hudOpen = true;
            Array.from(fileList).forEach(file => {
                const id = Date.now() + Math.random();
                this.uploads.push({ id, name: file.name, progress: 0, status: 'uploading', xhr: null });
                this._uploadOne(file, id);
            });
        },

        _uploadOne(file, itemId) {
            const formData = new FormData();
            formData.append('files', file);
            formData.append('csrfmiddlewaretoken', getCsrfToken());

            const xhr = new XMLHttpRequest();
            const find = () => this.uploads.find(u => u.id === itemId);
            const u0 = find(); if (u0) u0.xhr = xhr;

            xhr.upload.onprogress = e => {
                if (e.lengthComputable) { const u = find(); if (u) u.progress = Math.round((e.loaded / e.total) * 100); }
            };
            xhr.onload = () => {
                const u = find();
                if (u) { u.status = xhr.status >= 200 && xhr.status < 300 ? 'done' : 'error'; if (u.status === 'done') u.progress = 100; }
                if (this.uploads.every(u => u.status !== 'uploading')) setTimeout(() => { window.location.reload(); }, 1500);
            };
            xhr.onerror = () => { const u = find(); if (u) u.status = 'error'; };
            xhr.open('POST', '{% url "file-upload" %}');
            xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
            xhr.send(formData);
        },

        cancelAll() {
            this.uploads.forEach(u => { if (u.xhr && u.status === 'uploading') { u.xhr.abort(); u.status = 'cancelled'; } });
            setTimeout(() => { this.uploads = []; }, 800);
        },

        // ── Preview modal ────────────────────────────────────────────
        openPreview({ name, mimeType, url }) {
            this.currentIndex = this.fileList.findIndex(f => f.url === url);
            this.previewModal = { open: true, name, mimeType, url };
        },
        prevFile() {
            if (this.fileList.length < 2) return;
            this.currentIndex = (this.currentIndex - 1 + this.fileList.length) % this.fileList.length;
            const f = this.fileList[this.currentIndex];
            this.previewModal = { open: true, name: f.name, mimeType: f.mimeType, url: f.url };
        },
        nextFile() {
            if (this.fileList.length < 2) return;
            this.currentIndex = (this.currentIndex + 1) % this.fileList.length;
            const f = this.fileList[this.currentIndex];
            this.previewModal = { open: true, name: f.name, mimeType: f.mimeType, url: f.url };
        },
        closePreview() {
            this.previewModal.open = false;
            document.querySelectorAll('video, audio').forEach(el => el.pause());
        },

        // ── Expiry modal ─────────────────────────────────────────────
        openExpiry({ pk, expiresAt }) {
            this.expiryModal.pk = pk;
            this.expiryModal.expiryInput = expiresAt ? new Date(expiresAt).toISOString().slice(0, 16) : '';
            this.expiryModal.open = true;
        },
        saveExpiry() {
            const expires_at = this.expiryModal.expiryInput ? new Date(this.expiryModal.expiryInput).toISOString() : null;
            fetch(`/ui/files/${this.expiryModal.pk}/set-expiry/`, {
                method: 'POST',
                headers: { 'Content-Type': 'application/json', 'X-CSRFToken': getCsrfToken() },
                body: JSON.stringify({ expires_at }),
            }).then(r => r.json()).then(d => {
                this.expiryModal.open = false;
                window.dispatchEvent(new CustomEvent('expiry-updated', { detail: { pk: this.expiryModal.pk, expires_at: d.expires_at } }));
            });
        },
        clearExpiry() { this.expiryModal.expiryInput = ''; this.saveExpiry(); },

        // ── Toast ────────────────────────────────────────────────────
        copyAndToast(url) {
            const el = document.createElement('textarea');
            el.value = url; el.style.cssText = 'position:fixed;opacity:0';
            document.body.appendChild(el); el.select(); document.execCommand('copy'); document.body.removeChild(el);
            this.showToast('{% trans "Link copied!" %}');
        },
        showToast(msg) {
            this.toastMsg = msg;
            this.toastVisible = true;
            clearTimeout(this._toastTimer);
            this._toastTimer = setTimeout(() => { this.toastVisible = false; }, 2500);
        },
    };
}

function fileRow(pk, isPublic, expiresAt, publicUrl) {
    return {
        pk, isPublic, publicUrl,
        expiresAt: expiresAt || null,
        get isExpired() { return this.expiresAt && new Date(this.expiresAt) < new Date(); },
        init() {
            window.addEventListener('expiry-updated', e => {
                if (String(e.detail.pk) === String(this.pk)) this.expiresAt = e.detail.expires_at;
            });
        },
        togglePublic() {
            fetch(`/ui/files/${this.pk}/toggle-public/`, {
                method: 'POST', headers: { 'X-CSRFToken': getCsrfToken() },
            }).then(r => r.json()).then(d => { this.isPublic = d.is_public; });
        },
        formatExpiry(dt) { return dt ? new Date(dt).toLocaleDateString() : ''; },
        copyPublicUrl() {
            const url = this.publicUrl.startsWith('http') ? this.publicUrl : location.origin + this.publicUrl;
            const el = document.createElement('textarea');
            el.value = url; el.style.cssText = 'position:fixed;opacity:0';
            document.body.appendChild(el); el.select(); document.execCommand('copy'); document.body.removeChild(el);
            // Fire directly on window — $dispatch bubbles through <tr>/<table> unreliably
            window.dispatchEvent(new CustomEvent('copy-link', { detail: { url } }));
        },
    };
}

function getCsrfToken() {
    return document.cookie.split(';').find(c => c.trim().startsWith('csrftoken='))?.split('=')[1] || '';
}
</script>

<script id="file-list-data" type="application/json">
[{% for file in files %}{"name":"{{ file.name|escapejs }}","mimeType":"{{ file.mime_type|escapejs }}","url":"{{ file.download_url|escapejs }}"}{% if not forloop.last %},{% endif %}{% endfor %}]
</script>

{% endblock %}
