<script setup lang="ts">
import { ref, computed } from 'vue'
import type { TreeNode } from '@/types/git'

const props = defineProps<{
  nodes: TreeNode[]
  selectedPath?: string | null
  loading?: boolean
}>()

const emit = defineEmits<{
  select: [path: string]
}>()

const expandedDirs = ref<Set<string>>(new Set())

function toggleDir(path: string) {
  if (expandedDirs.value.has(path)) {
    expandedDirs.value.delete(path)
  } else {
    expandedDirs.value.add(path)
  }
  expandedDirs.value = new Set(expandedDirs.value)
}

function isExpanded(path: string): boolean {
  return expandedDirs.value.has(path)
}

function handleSelect(node: TreeNode) {
  if (node.type === 'directory') {
    toggleDir(node.path)
  } else {
    emit('select', node.path)
  }
}

function getFileIcon(name: string): string {
  const ext = name.split('.').pop()?.toLowerCase() || ''
  const icons: Record<string, string> = {
    ts: 'ts',
    tsx: 'tsx',
    js: 'js',
    jsx: 'jsx',
    vue: 'vue',
    json: 'json',
    md: 'md',
    css: 'css',
    scss: 'scss',
    html: 'html',
    svg: 'svg',
    png: 'img',
    jpg: 'img',
    jpeg: 'img',
    gif: 'img',
    ico: 'img',
    gitignore: 'git',
    env: 'env',
    yml: 'yml',
    yaml: 'yml',
    toml: 'toml',
    lock: 'lock'
  }
  return icons[ext] || 'file'
}
</script>

<template>
  <div class="project-tree">
    <div v-if="loading" class="loading">
      <div class="spinner"></div>
      Cargando archivos...
    </div>
    <div v-else-if="nodes.length === 0" class="empty">
      Sin archivos
    </div>
    <template v-else>
      <div
        v-for="node in nodes"
        :key="node.path"
        class="tree-node"
      >
        <div
          :class="['node-row', { selected: selectedPath === node.path }]"
          @click="handleSelect(node)"
        >
          <!-- Directory -->
          <template v-if="node.type === 'directory'">
            <span class="expand-icon">
              <svg
                :class="{ expanded: isExpanded(node.path) }"
                width="12"
                height="12"
                viewBox="0 0 24 24"
                fill="currentColor"
              >
                <path d="M8 5l8 7-8 7z" />
              </svg>
            </span>
            <span class="folder-icon">
              <svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor">
                <path v-if="isExpanded(node.path)" d="M19 20H5a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h6l2 2h6a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2z" />
                <path v-else d="M3 6a2 2 0 0 1 2-2h6l2 2h6a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V6z" />
              </svg>
            </span>
          </template>
          <!-- File -->
          <template v-else>
            <span class="expand-icon spacer"></span>
            <span :class="['file-icon', getFileIcon(node.name)]">
              <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
                <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" />
                <polyline points="14 2 14 8 20 8" />
              </svg>
            </span>
          </template>
          <span class="node-name">{{ node.name }}</span>
        </div>
        <!-- Recursive children -->
        <div v-if="node.type === 'directory' && isExpanded(node.path) && node.children" class="children">
          <ProjectTree
            :nodes="node.children"
            :selected-path="selectedPath"
            @select="emit('select', $event)"
          />
        </div>
      </div>
    </template>
  </div>
</template>

<style scoped>
.project-tree {
  font-size: 13px;
  user-select: none;
}

.loading,
.empty {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 1.5rem;
  color: var(--text-muted);
  font-size: 12px;
}

.spinner {
  width: 16px;
  height: 16px;
  border: 2px solid var(--border-color);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}

@keyframes spin {
  to { transform: rotate(360deg); }
}

.tree-node {
  /* Container for each node */
}

.node-row {
  display: flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.3rem 0.5rem;
  cursor: pointer;
  border-radius: 4px;
  transition: background 0.15s;
}

.node-row:hover {
  background: var(--bg-hover);
}

.node-row.selected {
  background: rgba(99, 102, 241, 0.15);
}

.expand-icon {
  width: 16px;
  height: 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  color: var(--text-muted);
  transition: transform 0.15s;
}

.expand-icon.spacer {
  visibility: hidden;
}

.expand-icon svg {
  transition: transform 0.15s;
}

.expand-icon svg.expanded {
  transform: rotate(90deg);
}

.folder-icon {
  width: 16px;
  height: 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  color: #f59e0b;
}

.file-icon {
  width: 16px;
  height: 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  color: var(--text-muted);
}

/* File type colors */
.file-icon.ts,
.file-icon.tsx {
  color: #3178c6;
}

.file-icon.js,
.file-icon.jsx {
  color: #f7df1e;
}

.file-icon.vue {
  color: #42b883;
}

.file-icon.json {
  color: #f5a623;
}

.file-icon.md {
  color: #519aba;
}

.file-icon.css,
.file-icon.scss {
  color: #563d7c;
}

.file-icon.html {
  color: #e34c26;
}

.file-icon.svg,
.file-icon.img {
  color: #a855f7;
}

.file-icon.git {
  color: #f05032;
}

.file-icon.env {
  color: #ecd53f;
}

.file-icon.yml {
  color: #cb171e;
}

.file-icon.lock {
  color: #6b7280;
}

.node-name {
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.children {
  padding-left: 1rem;
}
</style>
