<script setup>
import { onBeforeUnmount, onMounted, ref, nextTick, watch } from 'vue'
import Sortable from 'sortablejs'
import { accountApi } from '@/api/accountApi'
import { useDialog } from '@/composables/dialog'
import IconBtn from '@/components/ui/IconBtn.vue'

const dialog = useDialog()

const tags = ref([])
const loading = ref(false)
const error = ref(null)
const newName = ref('')
const reorderMode = ref(false)

function toggleReorder() {
  reorderMode.value = !reorderMode.value
}

async function load() {
  loading.value = true
  error.value = null
  try {
    tags.value = await accountApi.tags()
  } catch (e) {
    error.value = e.response?.data?.message || '불러오지 못했습니다.'
  } finally {
    loading.value = false
  }
}

// ===== 드래그앤드랍 정렬 (SortableJS, 터치 지원) =====
const listEl = ref(null)
let sortable = null
function initSortable() {
  if (sortable) {
    sortable.destroy()
    sortable = null
  }
  if (!listEl.value) return
  sortable = Sortable.create(listEl.value, {
    handle: '.drag-handle',
    animation: 150,
    onEnd: (evt) => {
      if (evt.oldIndex === evt.newIndex) return
      const arr = tags.value
      const moved = arr.splice(evt.oldIndex, 1)[0]
      arr.splice(evt.newIndex, 0, moved)
      persistOrder(arr.map((t) => t.id))
    },
  })
}
async function persistOrder(ids) {
  try {
    await accountApi.reorderTags(ids)
    await load()
  } catch (e) {
    alert(e.response?.data?.message || '순서 저장에 실패했습니다.')
    await load()
  }
}

async function addTag() {
  const name = newName.value.trim()
  if (!name) return
  try {
    await accountApi.createTag({ name })
    newName.value = ''
    await load()
  } catch (e) {
    alert(e.response?.data?.message || '추가에 실패했습니다.')
  }
}

async function saveTag(tag) {
  const name = (tag.name || '').trim()
  if (!name) return
  try {
    await accountApi.updateTag(tag.id, { name })
    await load()
  } catch (e) {
    alert(e.response?.data?.message || '수정에 실패했습니다.')
  }
}

async function removeTag(tag) {
  if (!(await dialog.confirm(`'${tag.name}' 태그를 삭제할까요?\n내역에서 연결도 해제됩니다.`, { title: '태그 삭제', danger: true }))) return
  try {
    await accountApi.removeTag(tag.id)
    await load()
  } catch (e) {
    alert(e.response?.data?.message || '삭제에 실패했습니다.')
  }
}

watch(reorderMode, async (on) => {
  if (on) {
    await nextTick()
    initSortable()
  } else {
    if (sortable) { sortable.destroy(); sortable = null }
  }
})

onMounted(load)
onBeforeUnmount(() => sortable?.destroy())
</script>

<template>
  <section class="tag-admin">
    <div class="top-row">
      <p class="hint">내가 등록한 태그는 나의 가계부 내역에서만 사용됩니다.</p>
      <button v-if="tags.length" type="button" class="text-btn reorder-btn" :class="{ active: reorderMode }" @click="toggleReorder">
        {{ reorderMode ? '완료' : '순서변경' }}
      </button>
    </div>

    <p v-if="reorderMode" class="hint sm">⠿ 손잡이를 끌어 순서를 바꾸세요. 끝나면 <b>완료</b>.</p>

    <form class="new-tag" @submit.prevent="addTag">
      <input v-model="newName" type="text" placeholder="새 태그 이름 (예: 식비, 정기결제)" />
      <IconBtn icon="plus" title="추가" variant="primary" type="submit" />
    </form>

    <p v-if="error" class="msg error">{{ error }}</p>
    <p v-if="loading" class="msg">불러오는 중...</p>

    <ul v-show="!loading && tags.length" ref="listEl" class="tag-list">
      <li v-for="t in tags" :key="t.id" :data-id="t.id" class="tag-row">
        <span v-if="reorderMode" class="drag-handle" title="드래그하여 순서 변경">≡</span>
        <input v-model="t.name" class="tag-name" @keyup.enter="saveTag(t)" :disabled="reorderMode" />
        <IconBtn v-if="!reorderMode" icon="check" title="저장" @click="saveTag(t)" />
        <IconBtn v-if="!reorderMode" icon="trash" title="삭제" variant="danger" @click="removeTag(t)" />
      </li>
    </ul>
    <p v-if="!loading && !tags.length" class="msg">등록된 태그가 없습니다.</p>
  </section>
</template>

<style scoped>
.tag-admin {
  max-width: 560px;
  margin: 0 auto;
}
.head {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
h1 {
  font-size: 1.5rem;
}
.top-row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0.5rem;
  margin-bottom: 0.25rem;
}
.hint {
  font-size: 0.85rem;
  opacity: 0.7;
  margin: 0.5rem 0 1rem;
}
.hint.sm {
  margin-top: -0.5rem;
  margin-bottom: 0.75rem;
}
.text-btn {
  flex-shrink: 0;
  font-size: 0.85rem;
  padding: 0.25rem 0.6rem;
  border: 1px solid var(--color-border);
  border-radius: 4px;
  background: transparent;
  color: var(--color-text);
  cursor: pointer;
  white-space: nowrap;
}
.text-btn.active {
  border-color: hsla(160, 100%, 37%, 1);
  color: hsla(160, 100%, 37%, 1);
}
input {
  padding: 0.5rem 0.7rem;
  border: 1px solid var(--color-border);
  border-radius: 4px;
  background: var(--color-background-soft);
  color: var(--color-text);
}
button {
  padding: 0.45rem 0.85rem;
  border: 1px solid var(--color-border);
  border-radius: 4px;
  background: var(--color-background-soft);
  color: var(--color-text);
  cursor: pointer;
}
button.danger {
  border-color: #c0392b;
  color: #c0392b;
}
.new-tag {
  display: flex;
  gap: 0.5rem;
  margin-bottom: 1rem;
}
.new-tag input {
  flex: 1;
}
.tag-list {
  list-style: none;
  padding-left: 0;
  margin: 0;
}
.tag-row {
  display: flex;
  gap: 0.5rem;
  align-items: center;
  padding: 0.4rem 0;
  border-bottom: 1px solid var(--color-border);
}
.drag-handle {
  cursor: grab;
  user-select: none;
  opacity: 0.5;
  font-size: 1.1rem;
  padding: 0 0.2rem;
  touch-action: none;
}
.drag-handle:active {
  cursor: grabbing;
}
.tag-name {
  flex: 1;
}
.msg {
  margin: 0.75rem 0;
}
.msg.error {
  color: #c0392b;
}
</style>
