<script setup>
import { ref, computed, watch, onMounted, nextTick, onUnmounted } from 'vue';
import { useDesignSystem } from '~/composables/useDesignSystem';
import { useNotifications } from '~/composables/useNotifications';
import { useTouchInteractions } from '~/composables/useTouchInteractions';
import LoadingStates from '~/components/base/LoadingStates.vue';
import ResponsiveContainer from '~/components/base/ResponsiveContainer.vue';
import BaseModal from '~/components/base/BaseModal.vue';
import RsButton from '~/components/RsButton.vue';

const props = defineProps({
  data: {
    type: Array,
    default: () => []
  },
  loading: {
    type: Boolean,
    default: false
  },
  allowDragDrop: {
    type: Boolean,
    default: true
  },
  allowMultiSelect: {
    type: Boolean,
    default: true
  },
  allowInlineEdit: {
    type: Boolean,
    default: true
  },
  showContextMenu: {
    type: Boolean,
    default: true
  }
});

const emit = defineEmits([
  'node-click', 'node-double-click', 'node-expand', 'node-collapse',
  'node-rename', 'node-delete', 'node-move', 'folder-create', 'file-upload',
  'context-menu', 'selection-change'
]);

// Design system and utilities
const { tokens, utils, dmsPatterns, statusColors } = useDesignSystem();
const { success, error, confirm } = useNotifications();
const { setupTouchInteractions } = useTouchInteractions();

// Tree state
const treeData = ref([]);
const selectedNodes = ref(new Set());
const expandedNodes = ref(new Set());
const editingNode = ref(null);
const dragNode = ref(null);
const dropTarget = ref(null);
const contextMenuNode = ref(null);

// UI state
const showContextMenu = ref(false);
const contextMenuPosition = ref({ x: 0, y: 0 });
const showNewFolderDialog = ref(false);
const showRenameDialog = ref(false);
const newFolderName = ref('');
const renameValue = ref('');

// Responsive state
const containerRef = ref(null);
const isMobile = ref(false);

// Build hierarchical tree from flat data
const buildTreeStructure = (flatData) => {
  const nodeMap = new Map();
  const roots = [];

  // First pass: create all nodes
  flatData.forEach(item => {
    nodeMap.set(item.id, {
      ...item,
      children: [],
      isExpanded: expandedNodes.value.has(item.id),
      isSelected: selectedNodes.value.has(item.id),
      level: 0
    });
  });

  // Second pass: build hierarchy
  flatData.forEach(item => {
    const node = nodeMap.get(item.id);
    if (item.parentId && nodeMap.has(item.parentId)) {
      const parent = nodeMap.get(item.parentId);
      parent.children.push(node);
      node.level = parent.level + 1;
    } else {
      roots.push(node);
    }
  });

  return roots;
};

// Computed tree structure
const computedTreeData = computed(() => {
  return buildTreeStructure(props.data);
});

// Update tree data when props change
watch(() => props.data, (newData) => {
  treeData.value = buildTreeStructure(newData);
}, { immediate: true });

// Node operations
const toggleNode = async (node) => {
  if (node.type === 'folder') {
    if (expandedNodes.value.has(node.id)) {
      expandedNodes.value.delete(node.id);
      emit('node-collapse', node);
    } else {
      expandedNodes.value.add(node.id);
      emit('node-expand', node);
    }
    
    // Rebuild tree to update expansion state
    treeData.value = buildTreeStructure(props.data);
  }
};

const selectNode = (node, multi = false) => {
  if (!multi || !props.allowMultiSelect) {
    selectedNodes.value.clear();
  }
  
  if (selectedNodes.value.has(node.id)) {
    selectedNodes.value.delete(node.id);
  } else {
    selectedNodes.value.add(node.id);
  }
  
  emit('selection-change', Array.from(selectedNodes.value));
  treeData.value = buildTreeStructure(props.data);
};

const handleNodeClick = (node, event) => {
  const isMultiSelect = event.ctrlKey || event.metaKey;
  selectNode(node, isMultiSelect);
  emit('node-click', node);
};

const handleNodeDoubleClick = (node) => {
  if (node.type === 'folder') {
    toggleNode(node);
  }
  emit('node-double-click', node);
};

// Context menu operations
const showNodeContextMenu = (node, event) => {
  if (!props.showContextMenu) return;
  
  event.preventDefault();
  contextMenuNode.value = node;
  contextMenuPosition.value = {
    x: event.clientX,
    y: event.clientY
  };
  showContextMenu.value = true;
  
  emit('context-menu', { node, position: contextMenuPosition.value });
};

const hideContextMenu = () => {
  showContextMenu.value = false;
  contextMenuNode.value = null;
};

// Editing operations
const startRename = (node) => {
  if (!props.allowInlineEdit) return;
  
  editingNode.value = node;
  renameValue.value = node.name;
  showRenameDialog.value = true;
  hideContextMenu();
};

const confirmRename = async () => {
  if (!editingNode.value || !renameValue.value.trim()) return;
  
  try {
    await emit('node-rename', {
      node: editingNode.value,
      newName: renameValue.value.trim()
    });
    
    success(`Successfully renamed to "${renameValue.value}"`);
    showRenameDialog.value = false;
    editingNode.value = null;
    renameValue.value = '';
  } catch (err) {
    error(`Failed to rename: ${err.message}`);
  }
};

const deleteNode = async (node) => {
  const confirmed = await confirm({
    title: 'Delete Item',
    message: `Are you sure you want to delete "${node.name}"?`,
    dangerous: true
  });
  
  if (confirmed) {
    try {
      await emit('node-delete', node);
      selectedNodes.value.delete(node.id);
      success(`Successfully deleted "${node.name}"`);
    } catch (err) {
      error(`Failed to delete: ${err.message}`);
    }
  }
  
  hideContextMenu();
};

// Folder operations
const createNewFolder = () => {
  newFolderName.value = '';
  showNewFolderDialog.value = true;
  hideContextMenu();
};

const confirmCreateFolder = async () => {
  if (!newFolderName.value.trim()) return;
  
  try {
    await emit('folder-create', {
      name: newFolderName.value.trim(),
      parentId: contextMenuNode.value?.id || null
    });
    
    success(`Folder "${newFolderName.value}" created successfully`);
    showNewFolderDialog.value = false;
    newFolderName.value = '';
  } catch (err) {
    error(`Failed to create folder: ${err.message}`);
  }
};

// Drag and drop
const handleDragStart = (node, event) => {
  if (!props.allowDragDrop) return;
  
  dragNode.value = node;
  event.dataTransfer.effectAllowed = 'move';
  event.dataTransfer.setData('text/plain', node.id);
};

const handleDragOver = (node, event) => {
  if (!props.allowDragDrop || !dragNode.value) return;
  if (node.type !== 'folder' || node.id === dragNode.value.id) return;
  
  event.preventDefault();
  dropTarget.value = node;
};

const handleDragLeave = () => {
  dropTarget.value = null;
};

const handleDrop = async (node, event) => {
  if (!props.allowDragDrop || !dragNode.value) return;
  
  event.preventDefault();
  
  try {
    await emit('node-move', {
      node: dragNode.value,
      targetParent: node
    });
    
    success(`Moved "${dragNode.value.name}" to "${node.name}"`);
  } catch (err) {
    error(`Failed to move: ${err.message}`);
  }
  
  dragNode.value = null;
  dropTarget.value = null;
};

// Mobile adaptations
const setupMobileInteractions = () => {
  if (!containerRef.value) return;
  
  const cleanup = setupTouchInteractions(containerRef.value);
  
  // Long press for context menu on mobile
  const { onLongPress } = useTouchInteractions();
  onLongPress((state) => {
    const element = document.elementFromPoint(state.x, state.y);
    const nodeElement = element?.closest('[data-node-id]');
    if (nodeElement) {
      const nodeId = nodeElement.dataset.nodeId;
      const node = props.data.find(n => n.id === nodeId);
      if (node) {
        showNodeContextMenu(node, {
          preventDefault: () => {},
          clientX: state.x,
          clientY: state.y
        });
      }
    }
  });
  
  return cleanup;
};

// File type icon helper
const getFileIcon = (node) => {
  if (node.type === 'folder') {
    return expandedNodes.value.has(node.id) ? 'mdi:folder-open' : 'mdi:folder';
  }
  
  const extension = node.name.split('.').pop()?.toLowerCase();
  return dmsPatterns.fileIcons[extension] || dmsPatterns.fileIcons.default;
};

// Status classes
const getNodeClasses = (node) => {
  return utils.composeClasses(
    'tree-node flex items-center p-2 rounded-md cursor-pointer transition-all duration-200',
    selectedNodes.value.has(node.id) 
      ? 'bg-primary/10 dark:bg-primary/20 text-primary'
      : 'hover:bg-gray-100 dark:hover:bg-gray-700 text-gray-700 dark:text-gray-300',
    dropTarget.value?.id === node.id ? 'bg-blue-100 dark:bg-blue-900/20 border-2 border-blue-400' : '',
    'select-none'
  );
};

// Lifecycle
onMounted(() => {
  isMobile.value = window.innerWidth < 768;
  window.addEventListener('resize', () => {
    isMobile.value = window.innerWidth < 768;
  });
  
  // Click outside to hide context menu
  document.addEventListener('click', hideContextMenu);
  
  // Setup mobile interactions
  const cleanup = setupMobileInteractions();
  
  // Cleanup on unmount
  onUnmounted(() => {
    document.removeEventListener('click', hideContextMenu);
    cleanup?.();
  });
});

// Utility functions
const formatFileSize = (bytes) => {
  if (!bytes || bytes === 0) return '0 B';
  const k = 1024;
  const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
  const i = Math.floor(Math.log(bytes) / Math.log(k));
  return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i];
};

const formatDate = (dateString) => {
  if (!dateString) return '-';
  return new Date(dateString).toLocaleDateString();
};
</script>

<template>
  <ResponsiveContainer
    ref="containerRef"
    layout="default"
    padding="md"
    class="windows-explorer-tree h-full"
  >
    <!-- Loading State -->
    <LoadingStates
      v-if="loading"
      type="skeleton-tree"
      :count="5"
      message="Loading file structure..."
    />

    <!-- Tree Content -->
    <div v-else class="tree-container h-full flex flex-col">
      <!-- Header Actions -->
      <div class="tree-header mb-4 flex items-center justify-between flex-shrink-0">
        <h3 class="text-lg font-semibold text-gray-900 dark:text-gray-100">
          File Explorer
        </h3>
        
        <div class="flex items-center space-x-2">
          <!-- New Folder Button -->
          <RsButton
            variant="secondary-outline"
            size="sm"
            @click="createNewFolder"
            :title="isMobile ? 'New Folder' : undefined"
          >
            <Icon name="mdi:folder-plus" class="w-4 h-4" />
            <span v-if="!isMobile" class="ml-2">New Folder</span>
          </RsButton>
          
          <!-- Upload Button -->
          <RsButton
            variant="primary"
            size="sm"
            @click="emit('file-upload')"
            :title="isMobile ? 'Upload Files' : undefined"
          >
            <Icon name="mdi:upload" class="w-4 h-4" />
            <span v-if="!isMobile" class="ml-2">Upload</span>
          </RsButton>
        </div>
      </div>

      <!-- Tree Nodes - Scrollable Container -->
      <div class="tree-nodes flex-1 overflow-auto min-h-0 space-y-1 pr-2">
        <div
          v-for="node in computedTreeData"
          :key="node.id"
          class="tree-node-container"
        >
          <!-- Root Node -->
          <div
            :data-node-id="node.id"
            :class="getNodeClasses(node)"
            :style="{ paddingLeft: `${node.level * 20}px` }"
            :draggable="allowDragDrop"
            @click="handleNodeClick(node, $event)"
            @dblclick="handleNodeDoubleClick(node)"
            @contextmenu="showNodeContextMenu(node, $event)"
            @dragstart="handleDragStart(node, $event)"
            @dragover="handleDragOver(node, $event)"
            @dragleave="handleDragLeave"
            @drop="handleDrop(node, $event)"
          >
            <!-- Expand/Collapse Icon -->
            <button
              v-if="node.type === 'folder' && node.children.length > 0"
              @click.stop="toggleNode(node)"
              class="expand-button mr-1 p-1 rounded hover:bg-gray-200 dark:hover:bg-gray-600 transition-colors"
            >
              <Icon
                :name="expandedNodes.has(node.id) ? 'mdi:chevron-down' : 'mdi:chevron-right'"
                class="w-4 h-4"
              />
            </button>
            <div v-else class="w-6"></div>

            <!-- File/Folder Icon -->
            <Icon
              :name="getFileIcon(node)"
              class="w-5 h-5 mr-2 flex-shrink-0"
              :class="node.type === 'folder' ? 'text-blue-600 dark:text-blue-400' : 'text-gray-600 dark:text-gray-400'"
            />

            <!-- Node Name -->
            <span class="node-name flex-1 truncate text-sm">
              {{ node.name }}
            </span>

            <!-- Node Metadata -->
            <div class="node-metadata flex items-center space-x-2 text-xs text-gray-500">
              <span v-if="node.size && node.type !== 'folder'">
                {{ formatFileSize(node.size) }}
              </span>
              <span v-if="node.modifiedAt">
                {{ formatDate(node.modifiedAt) }}
              </span>
            </div>
          </div>

          <!-- Child Nodes (Recursive) -->
          <div
            v-if="node.type === 'folder' && expandedNodes.has(node.id)"
            class="child-nodes ml-4"
          >
            <div
              v-for="child in node.children"
              :key="child.id"
              :data-node-id="child.id"
              :class="getNodeClasses(child)"
              :style="{ paddingLeft: `${(child.level - 1) * 20}px` }"
              :draggable="allowDragDrop"
              @click="handleNodeClick(child, $event)"
              @dblclick="handleNodeDoubleClick(child)"
              @contextmenu="showNodeContextMenu(child, $event)"
              @dragstart="handleDragStart(child, $event)"
              @dragover="handleDragOver(child, $event)"
              @dragleave="handleDragLeave"
              @drop="handleDrop(child, $event)"
            >
              <div class="w-6"></div>
              <Icon
                :name="getFileIcon(child)"
                class="w-5 h-5 mr-2 flex-shrink-0"
                :class="child.type === 'folder' ? 'text-blue-600 dark:text-blue-400' : 'text-gray-600 dark:text-gray-400'"
              />
              <span class="node-name flex-1 truncate text-sm">
                {{ child.name }}
              </span>
              <div class="node-metadata flex items-center space-x-2 text-xs text-gray-500">
                <span v-if="child.size && child.type !== 'folder'">
                  {{ formatFileSize(child.size) }}
                </span>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>

    <!-- Context Menu -->
    <Teleport to="body">
      <div
        v-if="showContextMenu && contextMenuNode"
        class="context-menu fixed z-50 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-600 rounded-md shadow-lg py-2 min-w-[160px]"
        :style="{
          left: `${contextMenuPosition.x}px`,
          top: `${contextMenuPosition.y}px`
        }"
      >
        <button
          @click="handleNodeDoubleClick(contextMenuNode)"
          class="context-menu-item w-full px-4 py-2 text-left text-sm hover:bg-gray-100 dark:hover:bg-gray-700 flex items-center"
        >
          <Icon name="mdi:open-in-new" class="w-4 h-4 mr-2" />
          Open
        </button>
        
        <button
          v-if="allowInlineEdit"
          @click="startRename(contextMenuNode)"
          class="context-menu-item w-full px-4 py-2 text-left text-sm hover:bg-gray-100 dark:hover:bg-gray-700 flex items-center"
        >
          <Icon name="mdi:pencil" class="w-4 h-4 mr-2" />
          Rename
        </button>
        
        <button
          @click="deleteNode(contextMenuNode)"
          class="context-menu-item w-full px-4 py-2 text-left text-sm hover:bg-gray-100 dark:hover:bg-gray-700 text-red-600 flex items-center"
        >
          <Icon name="mdi:delete" class="w-4 h-4 mr-2" />
          Delete
        </button>
        
        <hr class="my-1 border-gray-200 dark:border-gray-600">
        
        <button
          v-if="contextMenuNode.type === 'folder'"
          @click="createNewFolder"
          class="context-menu-item w-full px-4 py-2 text-left text-sm hover:bg-gray-100 dark:hover:bg-gray-700 flex items-center"
        >
          <Icon name="mdi:folder-plus" class="w-4 h-4 mr-2" />
          New Folder
        </button>
        
        <button
          @click="emit('file-upload', contextMenuNode)"
          class="context-menu-item w-full px-4 py-2 text-left text-sm hover:bg-gray-100 dark:hover:bg-gray-700 flex items-center"
        >
          <Icon name="mdi:upload" class="w-4 h-4 mr-2" />
          Upload Files
        </button>
      </div>
    </Teleport>

    <!-- New Folder Dialog -->
    <BaseModal
      v-model:visible="showNewFolderDialog"
      title="Create New Folder"
      size="md"
      @confirm="confirmCreateFolder"
      @cancel="showNewFolderDialog = false"
    >
      <div class="space-y-4">
        <div>
          <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
            Folder Name
          </label>
          <input
            v-model="newFolderName"
            type="text"
            placeholder="Enter folder name..."
            class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md 
                   bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100
                   focus:ring-2 focus:ring-primary focus:border-transparent"
            @keyup.enter="confirmCreateFolder"
          />
        </div>
      </div>
    </BaseModal>

    <!-- Rename Dialog -->
    <BaseModal
      v-model:visible="showRenameDialog"
      title="Rename Item"
      size="md"
      @confirm="confirmRename"
      @cancel="showRenameDialog = false"
    >
      <div class="space-y-4">
        <div>
          <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
            New Name
          </label>
          <input
            v-model="renameValue"
            type="text"
            class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md 
                   bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100
                   focus:ring-2 focus:ring-primary focus:border-transparent"
            @keyup.enter="confirmRename"
          />
        </div>
      </div>
    </BaseModal>
  </ResponsiveContainer>
</template>

<style scoped>
.windows-explorer-tree {
  @apply h-full overflow-hidden;
}

.tree-container {
  @apply h-full flex flex-col min-h-0;
}

.tree-nodes {
  @apply flex-1 overflow-y-auto min-h-0;
  /* Ensure smooth scrolling */
  scroll-behavior: smooth;
}

.tree-node {
  @apply relative;
}

.tree-node.dragging {
  @apply opacity-50;
}

.tree-node.drop-target {
  @apply bg-blue-100 dark:bg-blue-900/20 border-2 border-blue-400 border-dashed;
}

.expand-button {
  @apply transition-transform duration-200;
}

.context-menu {
  animation: contextMenuFadeIn 0.15s ease-out;
}

@keyframes contextMenuFadeIn {
  from {
    opacity: 0;
    transform: scale(0.95);
  }
  to {
    opacity: 1;
    transform: scale(1);
  }
}

.context-menu-item {
  @apply transition-colors duration-150;
}

/* Mobile optimizations */
@media (max-width: 768px) {
  .tree-node {
    @apply p-3;
  }
  
  .node-metadata {
    @apply hidden;
  }
  
  .expand-button {
    @apply p-2;
  }
}

/* Enhanced scrollbar styles */
.tree-nodes::-webkit-scrollbar {
  width: 8px;
}

.tree-nodes::-webkit-scrollbar-track {
  background: #f1f5f9;
  border-radius: 4px;
}

.tree-nodes::-webkit-scrollbar-thumb {
  background-color: #cbd5e1;
  border-radius: 4px;
  border: 2px solid #f1f5f9;
}

.tree-nodes::-webkit-scrollbar-thumb:hover {
  background-color: #94a3b8;
}

.tree-nodes::-webkit-scrollbar-corner {
  background: #f1f5f9;
}

/* Dark mode scrollbar */
.dark .tree-nodes::-webkit-scrollbar-track {
  background: #374151;
}

.dark .tree-nodes::-webkit-scrollbar-thumb {
  background-color: #6b7280;
  border-color: #374151;
}

.dark .tree-nodes::-webkit-scrollbar-thumb:hover {
  background-color: #9ca3af;
}

.dark .tree-nodes::-webkit-scrollbar-corner {
  background: #374151;
}
</style> 