<template>
  <v-container fluid class="pa-6">
    <!-- Header -->
    <v-row class="mb-6" v-if="!props.selectionMode">
      <v-col>
        <h1 class="text-h4 font-weight-bold">
          File Browser
        </h1>
        <p class="text-subtitle-1 text-grey mt-1">
          Manage your NDA documents and other files
        </p>
      </v-col>
    </v-row>

    <!-- Selection Mode Header -->
    <v-row v-if="props.selectionMode" class="mb-4">
      <v-col>
        <h2 class="text-h5 font-weight-bold">
          Select Files to Attach
        </h2>
        <p class="text-subtitle-2 text-grey mt-1">
          Click on files to attach them to your email
        </p>
      </v-col>
    </v-row>

    <!-- Breadcrumb Navigation -->
    <v-row class="mb-4" v-if="currentPath && !props.selectionMode">
      <v-col>
        <v-breadcrumbs :items="breadcrumbItems" class="pa-0">
          <template v-slot:item="{ item }">
            <v-breadcrumbs-item
              @click="navigateToFolder((item as any).path)"
              class="cursor-pointer"
            >
              {{ item.title }}
            </v-breadcrumbs-item>
          </template>
        </v-breadcrumbs>
      </v-col>
    </v-row>

    <!-- Action Bar -->
    <v-row class="mb-4">
      <v-col cols="12" md="6">
        <v-text-field
          v-model="searchQuery"
          placeholder="Search files..."
          prepend-inner-icon="mdi-magnify"
          variant="outlined"
          density="comfortable"
          clearable
          @update:model-value="filterFiles"
        />
      </v-col>
      <v-col cols="12" md="6" class="d-flex justify-end ga-2" v-if="!props.selectionMode">
        <v-btn
          color="secondary"
          size="large"
          @click="newFolderDialog = true"
          prepend-icon="mdi-folder-plus"
          variant="outlined"
        >
          New Folder
        </v-btn>
        <v-btn
          color="primary"
          size="large"
          @click="uploadDialog = true"
          prepend-icon="mdi-upload"
        >
          Upload Files
        </v-btn>
      </v-col>
    </v-row>

    <!-- Bulk Actions Bar (shown when items selected) -->
    <v-row v-if="selectedItems.length > 0 && !props.selectionMode" class="mb-4">
      <v-col>
        <v-alert
          type="info"
          variant="tonal"
          closable
          @click:close="selectedItems = []"
        >
          <div class="d-flex align-center justify-space-between">
            <span>{{ selectedItems.length }} item(s) selected</span>
            <div>
              <v-btn
                color="primary"
                variant="text"
                @click="downloadSelected"
                prepend-icon="mdi-download"
                class="mr-2"
              >
                Download
              </v-btn>
              <v-btn
                color="error"
                variant="text"
                @click="confirmDeleteSelected"
                prepend-icon="mdi-delete"
              >
                Delete
              </v-btn>
            </div>
          </div>
        </v-alert>
      </v-col>
    </v-row>

    <!-- File List -->
    <v-card>
      <v-data-table
        v-model="selectedItems"
        :headers="headers"
        :items="filteredFiles"
        :loading="loading"
        :items-per-page="25"
        class="elevation-0"
        show-select
        item-value="name"
      >
        <template v-slot:item.displayName="{ item }">
          <div 
            class="d-flex align-center py-2 cursor-pointer"
            @click="handleFileClick(item)"
          >
            <v-icon :icon="item.icon" class="mr-3" :color="item.isFolder ? 'primary' : ''" />
            <div>
              <div class="font-weight-medium">{{ item.displayName }}</div>
              <div class="text-caption text-grey" v-if="!item.isFolder">
                {{ item.extension.toUpperCase() }}
              </div>
            </div>
          </div>
        </template>

        <template v-slot:item.sizeFormatted="{ item }">
          <span class="text-body-2">{{ item.sizeFormatted }}</span>
        </template>

        <template v-slot:item.lastModified="{ item }">
          <span class="text-body-2">{{ formatDate(item.lastModified) }}</span>
        </template>

        <template v-slot:item.actions="{ item }">
          <div class="d-flex justify-end">
            <v-btn
              v-if="canPreview(item)"
              icon
              variant="text"
              size="small"
              @click.stop="previewFile(item)"
            >
              <v-icon>mdi-eye</v-icon>
              <v-tooltip activator="parent" location="top">Preview</v-tooltip>
            </v-btn>
            <v-btn
              v-if="!item.isFolder"
              icon
              variant="text"
              size="small"
              @click.stop="downloadFile(item)"
              :loading="downloadingFiles[item.name]"
            >
              <v-icon>mdi-download</v-icon>
              <v-tooltip activator="parent" location="top">Download</v-tooltip>
            </v-btn>
            <v-btn
              icon
              variant="text"
              size="small"
              @click.stop="confirmRename(item)"
            >
              <v-icon>mdi-rename-box</v-icon>
              <v-tooltip activator="parent" location="top">Rename</v-tooltip>
            </v-btn>
            <v-btn
              icon
              variant="text"
              size="small"
              color="error"
              @click.stop="confirmDelete(item)"
            >
              <v-icon>mdi-delete</v-icon>
              <v-tooltip activator="parent" location="top">Delete</v-tooltip>
            </v-btn>
          </div>
        </template>

        <template v-slot:no-data>
          <v-empty-state
            icon="mdi-folder-open-outline"
            title="No files found"
            :text="currentPath ? 'This folder is empty' : 'Upload your first file to get started'"
            class="my-6"
          />
        </template>
      </v-data-table>
    </v-card>

    <!-- Upload Dialog -->
    <v-dialog v-model="uploadDialog" max-width="600">
      <v-card>
        <v-card-title class="d-flex align-center">
          <v-icon class="mr-2">mdi-upload</v-icon>
          Upload Files
        </v-card-title>
        <v-card-text>
          <FileUploader
            @upload="handleFileUpload"
            @close="uploadDialog = false"
            :uploading="uploading"
            :current-path="currentPath"
          />
        </v-card-text>
      </v-card>
    </v-dialog>

    <!-- New Folder Dialog -->
    <v-dialog v-model="newFolderDialog" max-width="400">
      <v-card>
        <v-card-title>
          <v-icon class="mr-2">mdi-folder-plus</v-icon>
          Create New Folder
        </v-card-title>
        <v-card-text>
          <v-text-field
            v-model="newFolderName"
            label="Folder Name"
            variant="outlined"
            density="comfortable"
            autofocus
            @keyup.enter="createNewFolder"
          />
        </v-card-text>
        <v-card-actions>
          <v-spacer />
          <v-btn @click="newFolderDialog = false">Cancel</v-btn>
          <v-btn
            color="primary"
            variant="flat"
            @click="createNewFolder"
            :loading="creatingFolder"
            :disabled="!newFolderName"
          >
            Create
          </v-btn>
        </v-card-actions>
      </v-card>
    </v-dialog>

    <!-- Delete Confirmation Dialog -->
    <v-dialog v-model="deleteDialog" max-width="400">
      <v-card>
        <v-card-title>
          <v-icon class="mr-2" color="error">mdi-alert</v-icon>
          Confirm Delete
        </v-card-title>
        <v-card-text>
          Are you sure you want to delete "{{ fileToDelete?.displayName }}"?
          <span v-if="fileToDelete?.isFolder">
            This will delete all files and folders inside it.
          </span>
          This action cannot be undone.
        </v-card-text>
        <v-card-actions>
          <v-spacer />
          <v-btn @click="deleteDialog = false">Cancel</v-btn>
          <v-btn
            color="error"
            variant="flat"
            @click="deleteFile"
            :loading="deleting"
          >
            Delete
          </v-btn>
        </v-card-actions>
      </v-card>
    </v-dialog>

    <!-- Rename Dialog -->
    <v-dialog v-model="renameDialog" max-width="400">
      <v-card>
        <v-card-title>
          <v-icon class="mr-2">mdi-rename-box</v-icon>
          Rename {{ fileToRename?.isFolder ? 'Folder' : 'File' }}
        </v-card-title>
        <v-card-text>
          <v-text-field
            v-model="newName"
            :label="fileToRename?.isFolder ? 'New folder name' : 'New file name (without extension)'"
            variant="outlined"
            density="comfortable"
            autofocus
            @keyup.enter="renameFile"
            :hint="fileToRename?.isFolder ? '' : `Extension will be preserved (.${fileToRename?.extension})`"
            persistent-hint
          />
        </v-card-text>
        <v-card-actions>
          <v-spacer />
          <v-btn @click="renameDialog = false">Cancel</v-btn>
          <v-btn
            color="primary"
            variant="flat"
            @click="renameFile"
            :loading="renaming"
            :disabled="!newName || newName === getDisplayNameForRename()"
          >
            Rename
          </v-btn>
        </v-card-actions>
      </v-card>
    </v-dialog>

    <!-- File Preview Dialog -->
    <FilePreviewModal
      v-model="previewDialog"
      :file="fileToPreview"
    />
  </v-container>
</template>

<script setup lang="ts">
import { ref, computed, onMounted, watch } from 'vue';
import FileUploader from '~/components/FileUploader.vue';
import FilePreviewModal from '~/components/FilePreviewModal.vue';

interface FileItem {
  name: string;
  size: number;
  sizeFormatted: string;
  lastModified: string;
  extension: string;
  icon: string;
  displayName: string;
  isFolder: boolean;
  path?: string;
}

interface Props {
  selectionMode?: boolean;
}

interface Emits {
  (e: 'file-selected', file: FileItem): void;
}

const props = defineProps<Props>();
const emit = defineEmits<Emits>();

const toast = useToast();

// Data
const files = ref<FileItem[]>([]);
const filteredFiles = ref<FileItem[]>([]);
const selectedItems = ref<string[]>([]);
const searchQuery = ref('');
const loading = ref(false);
const uploading = ref(false);
const deleting = ref(false);
const renaming = ref(false);
const creatingFolder = ref(false);
const uploadDialog = ref(false);
const deleteDialog = ref(false);
const newFolderDialog = ref(false);
const previewDialog = ref(false);
const renameDialog = ref(false);
const fileToDelete = ref<FileItem | null>(null);
const fileToPreview = ref<FileItem | null>(null);
const fileToRename = ref<FileItem | null>(null);
const downloadingFiles = ref<Record<string, boolean>>({});
const currentPath = ref('');
const newFolderName = ref('');
const newName = ref('');

// Table headers
const headers = [
  { title: 'Name', key: 'displayName', sortable: true },
  { title: 'Size', key: 'sizeFormatted', sortable: true },
  { title: 'Modified', key: 'lastModified', sortable: true },
  { title: 'Actions', key: 'actions', sortable: false, align: 'end' as const },
];

// Breadcrumb items
const breadcrumbItems = computed(() => {
  const items = [
    { title: 'Root', path: '', to: '#' }
  ];
  
  if (currentPath.value) {
    const parts = currentPath.value.split('/').filter(Boolean);
    let accumulated = '';
    
    parts.forEach(part => {
      accumulated += part + '/';
      items.push({
        title: part,
        path: accumulated,
        to: '#'
      });
    });
  }
  
  return items;
});

// Load files with retry logic
const loadFiles = async (retryCount = 0) => {
  loading.value = true;
  try {
    // Get current user email for email attachments
    const user = useDirectusUser();
    const userEmail = user.value?.email || '';
    
    const response = await $fetch<{
      success: boolean;
      files: FileItem[];
      count: number;
      currentPath: string;
    }>('/api/files/list-with-attachments', {
      headers: {
        'x-tag': '094ut234'
      },
      params: {
        prefix: currentPath.value,
        recursive: false,
        includeEmailAttachments: true,
        userEmail: userEmail
      },
      timeout: 15000 // 15 second timeout
    });
    files.value = response.files || [];
    filteredFiles.value = response.files || [];
  } catch (error: any) {
    console.error(`Failed to load files (attempt ${retryCount + 1}/3):`, error);
    
    // Retry on certain errors
    if (retryCount < 2 && (
      error.message?.includes('Failed to fetch') ||
      error.message?.includes('Network') ||
      error.statusCode === 500 ||
      error.statusCode === 503
    )) {
      console.log('Retrying file load...');
      setTimeout(() => {
        loadFiles(retryCount + 1);
      }, (retryCount + 1) * 1000); // Exponential backoff
    } else {
      toast.error('Failed to load files. Please refresh the page.');
      files.value = [];
      filteredFiles.value = [];
    }
  } finally {
    if (retryCount === 0 || retryCount === 2) {
      loading.value = false;
    }
  }
};

// Filter files based on search
const filterFiles = () => {
  if (!searchQuery.value) {
    filteredFiles.value = files.value;
    return;
  }
  
  const query = searchQuery.value.toLowerCase();
  filteredFiles.value = files.value.filter(file => 
    file.displayName.toLowerCase().includes(query)
  );
};

// Handle file/folder click
const handleFileClick = (item: FileItem) => {
  if (props.selectionMode && !item.isFolder) {
    // In selection mode, emit the file for attachment
    emit('file-selected', {
      ...item,
      path: item.name
    });
    return;
  }
  
  if (item.isFolder) {
    navigateToFolder(item.name);
  } else if (canPreview(item)) {
    previewFile(item);
  }
};

// Navigate to folder
const navigateToFolder = (folderPath: string) => {
  currentPath.value = folderPath;
  searchQuery.value = '';
  loadFiles();
};

// Check if file can be previewed
const canPreview = (file: FileItem) => {
  if (file.isFolder) return false;
  const previewableExtensions = ['jpg', 'jpeg', 'png', 'gif', 'svg', 'webp', 'pdf'];
  return previewableExtensions.includes(file.extension);
};

// Preview file
const previewFile = (file: FileItem) => {
  fileToPreview.value = file;
  previewDialog.value = true;
};

// Handle file upload
const handleFileUpload = async (uploadedFiles: File[]) => {
  uploading.value = true;
  
  try {
    const formData = new FormData();
    uploadedFiles.forEach(file => {
      formData.append('file', file);
    });
    
    await $fetch('/api/files/upload', {
      method: 'POST',
      body: formData,
      params: {
        path: currentPath.value,
      }
    });
    
    toast.success(`${uploadedFiles.length} file(s) uploaded successfully`);
    uploadDialog.value = false;
    await loadFiles();
  } catch (error) {
    toast.error('Failed to upload files');
  } finally {
    uploading.value = false;
  }
};

// Create new folder
const createNewFolder = async () => {
  if (!newFolderName.value) return;
  
  creatingFolder.value = true;
  try {
    const folderPath = currentPath.value 
      ? `${currentPath.value}${newFolderName.value}/`
      : `${newFolderName.value}/`;
    
    await $fetch('/api/files/create-folder', {
      method: 'POST',
      body: { folderPath },
    });
    
    toast.success('Folder created successfully');
    newFolderDialog.value = false;
    newFolderName.value = '';
    await loadFiles();
  } catch (error) {
    toast.error('Failed to create folder');
  } finally {
    creatingFolder.value = false;
  }
};

// Download file (with special handling for Safari)
const downloadFile = async (file: FileItem) => {
  downloadingFiles.value[file.name] = true;
  
  try {
    // Extract clean filename for download
    let filename = file.displayName;
    if (!filename.includes('.') && file.extension) {
      filename += '.' + file.extension;
    }
    
    // Check if Safari (iOS or desktop)
    const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
    
    if (isSafari) {
      // For Safari, open in new window to force proper filename handling
      const downloadUrl = `/api/files/proxy-download?fileName=${encodeURIComponent(file.name)}`;
      window.location.href = downloadUrl;
    } else {
      // For other browsers, use blob approach
      const response = await fetch(`/api/files/proxy-download?fileName=${encodeURIComponent(file.name)}`);
      
      if (!response.ok) {
        throw new Error('Failed to download file');
      }
      
      const blob = await response.blob();
      
      // Create object URL from blob
      const objectUrl = URL.createObjectURL(blob);
      
      // Create a link element
      const link = document.createElement('a');
      link.href = objectUrl;
      link.download = filename;
      link.style.display = 'none';
      document.body.appendChild(link);
      link.click();
      
      // Clean up
      setTimeout(() => {
        document.body.removeChild(link);
        URL.revokeObjectURL(objectUrl);
      }, 100);
    }
  } catch (error) {
    toast.error('Failed to download file');
  } finally {
    // Add delay for Safari to prevent immediate loading state removal
    setTimeout(() => {
      downloadingFiles.value[file.name] = false;
    }, 1000);
  }
};

// Download selected files
const downloadSelected = async () => {
  const selectedFiles = files.value.filter(file => selectedItems.value.includes(file.name) && !file.isFolder);
  
  if (selectedFiles.length === 0) {
    toast.warning('Please select files to download (folders cannot be downloaded)');
    return;
  }
  
  // Download files sequentially with a small delay
  for (const file of selectedFiles) {
    await downloadFile(file);
    await new Promise(resolve => setTimeout(resolve, 500)); // Small delay between downloads
  }
  
  selectedItems.value = [];
};

// Confirm delete selected
const confirmDeleteSelected = () => {
  const itemsToDelete = files.value.filter(file => selectedItems.value.includes(file.name));
  
  if (itemsToDelete.length === 0) return;
  
  const hasFolder = itemsToDelete.some(item => item.isFolder);
  const message = hasFolder 
    ? `Are you sure you want to delete ${itemsToDelete.length} item(s)? This includes folders with all their contents.`
    : `Are you sure you want to delete ${itemsToDelete.length} file(s)?`;
  
  if (confirm(message)) {
    deleteSelected();
  }
};

// Delete selected items
const deleteSelected = async () => {
  const itemsToDelete = files.value.filter(file => selectedItems.value.includes(file.name));
  
  deleting.value = true;
  let successCount = 0;
  let errorCount = 0;
  
  try {
    for (const item of itemsToDelete) {
      try {
        await $fetch('/api/files/delete', {
          method: 'POST',
          body: { 
            fileName: item.name,
            isFolder: item.isFolder,
          },
        });
        successCount++;
      } catch (error) {
        errorCount++;
      }
    }
    
    if (successCount > 0 && errorCount === 0) {
      toast.success(`${successCount} item(s) deleted successfully`);
    } else if (successCount > 0 && errorCount > 0) {
      toast.warning(`${successCount} item(s) deleted, ${errorCount} failed`);
    } else {
      toast.error('Failed to delete items');
    }
    
    selectedItems.value = [];
    await loadFiles();
  } finally {
    deleting.value = false;
  }
};

// Confirm delete
const confirmDelete = (file: FileItem) => {
  fileToDelete.value = file;
  deleteDialog.value = true;
};

// Delete file
const deleteFile = async () => {
  if (!fileToDelete.value) return;
  
  deleting.value = true;
  try {
    await $fetch('/api/files/delete', {
      method: 'POST',
      body: { 
        fileName: fileToDelete.value.name,
        isFolder: fileToDelete.value.isFolder,
      },
    });
    
    toast.success(fileToDelete.value.isFolder ? 'Folder deleted successfully' : 'File deleted successfully');
    deleteDialog.value = false;
    await loadFiles();
  } catch (error) {
    toast.error('Failed to delete');
  } finally {
    deleting.value = false;
    fileToDelete.value = null;
  }
};

// Confirm rename
const confirmRename = (file: FileItem) => {
  fileToRename.value = file;
  // Set initial value to current display name without extension
  if (file.isFolder) {
    newName.value = file.displayName;
  } else {
    // Remove extension from display name
    const extIndex = file.displayName.lastIndexOf('.');
    newName.value = extIndex > -1 ? file.displayName.substring(0, extIndex) : file.displayName;
  }
  renameDialog.value = true;
};

// Get display name for rename comparison
const getDisplayNameForRename = () => {
  if (!fileToRename.value) return '';
  if (fileToRename.value.isFolder) {
    return fileToRename.value.displayName;
  } else {
    // Remove extension from display name
    const extIndex = fileToRename.value.displayName.lastIndexOf('.');
    return extIndex > -1 ? fileToRename.value.displayName.substring(0, extIndex) : fileToRename.value.displayName;
  }
};

// Rename file
const renameFile = async () => {
  if (!fileToRename.value || !newName.value) return;
  
  renaming.value = true;
  try {
    await $fetch('/api/files/rename', {
      method: 'POST',
      body: {
        oldName: fileToRename.value.name,
        newName: newName.value,
        isFolder: fileToRename.value.isFolder,
      },
    });
    
    toast.success(fileToRename.value.isFolder ? 'Folder renamed successfully' : 'File renamed successfully');
    renameDialog.value = false;
    await loadFiles();
  } catch (error: any) {
    toast.error(error.data?.statusMessage || 'Failed to rename');
  } finally {
    renaming.value = false;
    fileToRename.value = null;
    newName.value = '';
  }
};

// Helpers
const formatDate = (date: string) => {
  return new Date(date).toLocaleDateString('en-US', {
    year: 'numeric',
    month: 'short',
    day: 'numeric',
    hour: '2-digit',
    minute: '2-digit',
  });
};

// Load files on mount
onMounted(() => {
  loadFiles();
});
</script>

<style scoped>
.cursor-pointer {
  cursor: pointer;
}
</style>
