<script setup lang="ts">
import { computed, nextTick, ref, watch } from 'vue';
import type { Folder } from '@/store/useFoldersStore';

type FolderChild =
  | { type: 'icon'; id: string; icon?: { name: string; img?: string; text?: string; bgColor?: string; url?: string } }
  | { type: 'widget'; id: string; widget?: { component: string } };

const props = defineProps<{
  open: boolean;
  folder: Folder | null;
  children: FolderChild[];
}>();

const emit = defineEmits<{
  (e: 'close'): void;
  (e: 'rename', payload: { id: string; name: string }): void;
  (e: 'remove', payload: { folderId: string; child: FolderChild }): void;
  (e: 'open-item', payload: FolderChild): void;
}>();

const localName = ref('文件夹');
const editingName = ref(false);
const nameInputRef = ref<HTMLInputElement | null>(null);

watch(
  () => props.folder?.name,
  name => {
    localName.value = name ?? '文件夹';
  },
  { immediate: true }
);

watch(
  () => props.folder?.id,
  () => {
    editingName.value = false;
  }
);

watch(
  () => props.open,
  () => {
    editingName.value = false;
  }
);

const handleRename = () => {
  if (!props.folder) return;
  const name = localName.value.trim() || '文件夹';
  emit('rename', { id: props.folder.id, name });
};

const focusRenameInput = async () => {
  await nextTick();
  const input = nameInputRef.value;
  if (!input) return;
  input.focus();
  const len = input.value.length;
  input.setSelectionRange(len, len);
};

const startRename = () => {
  editingName.value = true;
};

const finishRename = () => {
  editingName.value = false;
  handleRename();
};

const badgeLabel = computed(() => localName.value || '文件夹');

const initialText = (child: FolderChild) => {
  if (child.type === 'icon') {
    const label = child.icon?.text?.trim() || child.icon?.name || '';
    return label ? label.charAt(0) : 'I';
  }
  return 'W';
};

const labelFor = (child: FolderChild) =>
  child.type === 'icon' ? child.icon?.name ?? '未命名' : child.widget?.component ?? 'Widget';
</script>

<template>
  <teleport to="body">
    <div
      class="folder-dialog-overlay"
      :class="{ 'is-open': open && folder }"
      @click.self="emit('close')"
    >
      <transition name="folder-dialog">
        <div v-if="open && folder" class="folder-dialog-wrap">
          <div class="folder-title">
            <transition name="folder-title" mode="out-in" @after-enter="focusRenameInput">
              <button v-if="!editingName" key="view" type="button" class="folder-title-pill" @click="startRename">
                {{ badgeLabel }}
              </button>
              <input
                v-else
                key="edit"
                ref="nameInputRef"
                v-model="localName"
                class="folder-title-input"
                @keyup.enter="finishRename"
                @blur="finishRename"
              />
            </transition>
          </div>
          <div class="folder-dialog">
            <div v-if="children.length" class="folder-grid">
              <div
                v-for="child in children"
                :key="`${child.type}-${child.id}`"
                class="folder-item"
                @click="emit('open-item', child)"
              >
                <div
                  class="folder-item-icon"
                  :data-type="child.type"
                  :style="child.type === 'icon' && child.icon?.bgColor ? { backgroundColor: child.icon.bgColor } : {}"
                >
                  <img v-if="child.type === 'icon' && child.icon?.img" :src="child.icon.img" :alt="child.icon?.name" />
                  <span v-else>{{ initialText(child) }}</span>
                </div>
                <div class="folder-item-label">{{ labelFor(child) }}</div>
                <button
                  type="button"
                  class="folder-item-remove"
                  @click.stop="emit('remove', { folderId: folder.id, child })"
                >
                  移出
                </button>
              </div>
            </div>
            <div v-else class="folder-empty">空</div>
          </div>
        </div>
      </transition>
    </div>
  </teleport>
</template>

<style scoped lang="scss">
@import '@/styles/tokens.scss';

.folder-dialog-overlay {
  position: fixed;
  inset: 0;
  background: rgba(10, 12, 20, 0.32);
  backdrop-filter: blur(18px) saturate(140%);
  -webkit-backdrop-filter: blur(18px) saturate(140%);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: $z-index-menu;
  opacity: 0;
  pointer-events: none;
}

.folder-dialog-overlay.is-open {
  opacity: 1;
  pointer-events: auto;
}

.folder-dialog-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
}

.folder-title {
  display: flex;
  align-items: center;
  justify-content: center;
}

.folder-title-pill {
  min-width: 180px;
  height: 36px;
  padding: 0 16px;
  border-radius: 10px;
  border: none;
  background: transparent;
  color: #fff;
  font-size: 16px;
  font-weight: 600;
  letter-spacing: 0.5px;
  box-shadow: none;
  cursor: pointer;
  box-sizing: border-box;
}

.folder-title-input {
  min-width: 180px;
  height: 36px;
  padding: 0 16px;
  border-radius: 10px;
  border: 1px solid rgba(255, 255, 255, 0.35);
  background: rgba(255, 255, 255, 0.38);
  backdrop-filter: blur(22px) saturate(160%);
  -webkit-backdrop-filter: blur(22px) saturate(160%);
  color: rgba(0, 0, 0, 0.85);
  font-size: 16px;
  font-weight: 600;
  outline: none;
  text-align: center;
  box-shadow: 0 30px 80px rgba(0, 0, 0, 0.2);
  box-sizing: border-box;
}

.folder-dialog {
  width: min(720px, 90vw);
  min-height: 200px;
  padding: 22px 26px 26px;
  border-radius: 22px;
  border: 1px solid rgba(255, 255, 255, 0.35);
  background: rgba(255, 255, 255, 0.38);
  backdrop-filter: blur(22px) saturate(160%);
  box-shadow: 0 30px 80px rgba(0, 0, 0, 0.2);
}

.folder-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(90px, 1fr));
  gap: 16px;
}

.folder-item {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 6px 4px 10px;
  border-radius: 14px;
  cursor: pointer;
  transition: transform $motion-duration-sm $motion-easing-standard, background $motion-duration-sm $motion-easing-standard;

  &:hover {
    transform: translateY(-2px);
    background: rgba(255, 255, 255, 0.2);
  }

  &:hover .folder-item-remove {
    opacity: 1;
    transform: translateY(0);
  }
}

.folder-item-icon {
  width: 56px;
  height: 56px;
  border-radius: 16px;
  background: rgba(255, 255, 255, 0.8);
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  color: #222;
  box-shadow: 0 10px 20px rgba(0, 0, 0, 0.15);
  overflow: hidden;

  img {
    width: 100%;
    height: 100%;
    object-fit: cover;
  }

  &[data-type='widget'] {
    background: rgba(0, 0, 0, 0.08);
  }
}

.folder-item-label {
  font-size: 12px;
  color: rgba(0, 0, 0, 0.7);
  text-align: center;
  max-width: 100%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.folder-item-remove {
  position: absolute;
  top: 2px;
  right: 6px;
  border: none;
  background: rgba(255, 255, 255, 0.85);
  color: #c0392b;
  border-radius: 999px;
  padding: 2px 8px;
  font-size: 11px;
  cursor: pointer;
  opacity: 0;
  transform: translateY(-4px);
  transition: opacity $motion-duration-sm $motion-easing-standard, transform $motion-duration-sm $motion-easing-standard;
}

.folder-empty {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 160px;
  color: rgba(255, 255, 255, 0.85);
  font-weight: 600;
}

.folder-dialog-enter-active {
  transition: transform 220ms $motion-easing-standard;
}

.folder-dialog-enter-from {
  transform: translateY(14px) scale(0.98);
}

.folder-title-enter-active,
.folder-title-leave-active {
  transition: opacity 90ms $motion-easing-standard;
}

.folder-title-enter-from,
.folder-title-leave-to {
  opacity: 0;
}
</style>
