<template>
  <div class="tn">
    <div
      v-if="node.type === 'folder'"
      class="folder"
      :style="{ paddingLeft: 8 + depth * 14 + 'px' }"
      @click="open = !open"
    >
      <svg :class="{ open }" width="10" height="10" viewBox="0 0 10 10"><path d="M3 1l5 4-5 4" stroke="currentColor" stroke-width="1.5" fill="none" stroke-linecap="round" stroke-linejoin="round"/></svg>
      <svg width="14" height="14" viewBox="0 0 24 24" fill="none"><path d="M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V7z" stroke="currentColor" stroke-width="1.5"/></svg>
      <span class="label">{{ node.label }}</span>
      <span class="count" v-if="node.children?.length">{{ countApis(node) }}</span>
      <div class="row-actions">
        <button class="xs-btn ghost icon" @click.stop="addApiHere" title="新增接口">+</button>
        <button class="xs-btn ghost icon" @click.stop="addFolderHere" title="新增子分组">⊟</button>
      </div>
    </div>

    <div
      v-else-if="node.type === 'api'"
      class="api"
      :class="{ active: node.filePath === selectedFile, hidden: !match }"
      :style="{ paddingLeft: 8 + depth * 14 + 'px' }"
      @click="onClick"
    >
      <span class="method" :class="'m-' + (node.method || 'GET').toLowerCase()">{{ node.method }}</span>
      <span class="name">{{ node.label }}</span>
      <span v-if="node.status === 'developing'" class="status dot" title="开发中">●</span>
    </div>

    <template v-if="node.type === 'folder' && open">
      <TreeNode
        v-for="c in node.children"
        :key="c.id"
        :node="c"
        :depth="depth + 1"
        :keyword="keyword"
        :selected-file="selectedFile"
        @select-api="$emit('select-api', $event)"
      />
      <div
        v-if="!node.children?.length"
        class="empty-folder"
        :style="{ paddingLeft: 12 + (depth + 1) * 14 + 'px' }"
      >
        空白分组
      </div>
    </template>
  </div>
</template>

<script setup lang="ts">
import { computed, ref } from 'vue'
import { useWorkspaceStore } from '@/stores/workspace'
import type { ApiTreeNode } from '@/types'

const props = defineProps<{
  node: ApiTreeNode
  depth: number
  keyword: string
  selectedFile?: string | null
}>()

const emit = defineEmits<{
  (e: 'select-api', n: ApiTreeNode): void
}>()

const workspaceStore = useWorkspaceStore()
const open = ref(props.depth < 2)

const match = computed(() => {
  if (!props.keyword) return true
  return props.node.label.toLowerCase().includes(props.keyword.toLowerCase())
})

function countApis(n: ApiTreeNode): number {
  if (n.type === 'api') return 1
  return (n.children ?? []).reduce((sum, c) => sum + countApis(c), 0)
}

async function addApiHere() {
  if (!workspaceStore.rootDir) return
  const name = prompt('接口名称', '新建接口')
  if (!name) return
  const created = await window.xs.api.create(workspaceStore.rootDir, '', {
    name, method: 'GET', url: '/'
  })
  const apiNode: ApiTreeNode = {
    type: 'api',
    id: created.id,
    label: name,
    method: 'GET',
    filePath: created.filePath
  }
  if (props.node.type === 'folder') {
    props.node.children = props.node.children ?? []
    props.node.children.push(apiNode)
    await workspaceStore.saveProject()
  }
}

async function addFolderHere() {
  const name = prompt('分组名称', '新子分组')
  if (!name) return
  if (props.node.type === 'folder') {
    props.node.children = props.node.children ?? []
    props.node.children.push({
      type: 'folder', id: `f-${Date.now()}`, label: name, children: []
    })
    await workspaceStore.saveProject()
  }
}

function onClick() {
  emit('select-api', props.node)
}
</script>

<style lang="scss" scoped>
.tn { user-select: none; }
.folder, .api {
  display: flex; align-items: center; gap: 6px;
  padding: 5px 8px;
  font-size: $font-sm;
  cursor: pointer;
  border-radius: $radius-sm;
  color: $text-secondary;
  &:hover { background: $bg-hover; color: $text-primary; }
  .row-actions { display: none; gap: 2px; margin-left: auto; }
  &:hover .row-actions { display: flex; }
}
.folder {
  svg:first-child { transition: transform .15s ease; color: $text-tertiary; }
  svg.open { transform: rotate(90deg); }
  svg:nth-child(2) { color: $primary; opacity: .8; }
  .label { font-weight: 500; }
  .count {
    margin-left: 4px;
    font-size: $font-xs;
    color: $text-tertiary;
    background: $bg-elevated;
    padding: 0 5px;
    border-radius: 8px;
  }
}
.api {
  &.hidden { opacity: .3; pointer-events: none; }
  &.active {
    background: linear-gradient(90deg, $primary-bg, transparent);
    color: $text-primary;
    border-left: 2px solid $primary;
    .name { color: $text-primary; }
  }
  .method {
    font-size: 9px;
    padding: 1px 4px;
    border-radius: 3px;
    font-weight: 700;
    color: #0a1428;
    letter-spacing: .5px;
    width: 42px;
    text-align: center;
  }
  .m-get { background: $m-get; }
  .m-post { background: $m-post; }
  .m-put { background: $m-put; }
  .m-delete { background: $m-delete; }
  .m-patch { background: $m-patch; }
  .m-head, .m-options { background: #6b85b3; color: #fff; }

  .name { color: $text-primary; flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .status { color: $primary; font-size: 10px; }
}
.empty-folder {
  font-size: $font-xs;
  color: $text-tertiary;
  padding: 4px 0;
  font-style: italic;
}

.icon { padding: 2px 6px; font-size: 12px; line-height: 1; }
</style>
