import { nextTick } from 'vue' export function useAdminCustomItems({ api, toast, customItems, customItemPage, customItemLimit, customItemPageCount, customItemQuery, customItemOrphanOnly, customItemModalOpen, customItemDeleteModalOpen, customItemModalHistoryActive, modalTargetCustomItem, customItemModalDraftLabel, customItemModalLabelSaving, customItemModalTargetGameId, customItemModalGameQuery, customItemModalGameSort, games, selectedGameId, refreshCustomItems, loadGame, setTab, selectAdminGame, resetMessages, success, error, }) { function submitCustomItemSearch() { customItemPage.value = 1 refreshCustomItems() } function toggleCustomItemOrphanOnly() { customItemPage.value = 1 refreshCustomItems() } function changeCustomItemLimit(limit) { customItemLimit.value = limit customItemPage.value = 1 refreshCustomItems() } function moveCustomItemPage(direction) { const nextPage = customItemPage.value + direction if (nextPage < 1 || nextPage > customItemPageCount.value) return customItemPage.value = nextPage refreshCustomItems() } function pushCustomItemModalHistoryState() { if (typeof window === 'undefined') return window.history.pushState({ ...(window.history.state || {}), adminCustomItemModal: true }, '', window.location.href) customItemModalHistoryActive.value = true } function openCustomItemModal(item) { modalTargetCustomItem.value = item || null customItemModalDraftLabel.value = item?.label || '' customItemModalTargetGameId.value = '' customItemModalGameQuery.value = '' customItemModalGameSort.value = 'recent' customItemModalOpen.value = true pushCustomItemModalHistoryState() } function closeCustomItemModal({ fromPopState = false } = {}) { customItemModalOpen.value = false customItemDeleteModalOpen.value = false modalTargetCustomItem.value = null customItemModalDraftLabel.value = '' customItemModalLabelSaving.value = false customItemModalTargetGameId.value = '' customItemModalGameQuery.value = '' customItemModalGameSort.value = 'recent' if (fromPopState) { customItemModalHistoryActive.value = false return } if (customItemModalHistoryActive.value && typeof window !== 'undefined') { customItemModalHistoryActive.value = false window.history.back() } } function openCustomItemDeleteModal(item) { if (!item) return if (item.sourceType === 'user' && (item.usageCount > 0 || item.linkedGames.length > 0)) { error.value = '사용 중이거나 템플릿에 연결된 사용자 업로드 이미지는 먼저 참조를 정리해야 삭제할 수 있어요.' return } modalTargetCustomItem.value = item customItemDeleteModalOpen.value = true } function closeCustomItemDeleteModal() { customItemDeleteModalOpen.value = false } function jumpToGameAdmin(gameId) { if (!gameId) return closeCustomItemModal() setTab('game-admin') nextTick(() => { selectAdminGame(gameId) }) } async function removeCustomItem(item = modalTargetCustomItem.value) { resetMessages() if (!item) return if (item.sourceType === 'user' && (item.usageCount > 0 || item.linkedGames.length > 0)) { error.value = '사용 중이거나 템플릿에 연결된 사용자 업로드 이미지는 먼저 참조를 정리해야 삭제할 수 있어요.' return } try { await api.deleteAdminCustomItem(item.id) closeCustomItemDeleteModal() closeCustomItemModal() await refreshCustomItems() success.value = item.sourceType === 'template' ? '선택한 템플릿 아이템을 제거했어요.' : '사용자 업로드 이미지를 삭제했어요.' } catch (e) { error.value = item.sourceType === 'template' ? '템플릿 아이템 제거에 실패했어요.' : '사용자 업로드 이미지 삭제에 실패했어요.' } } async function removeUnusedCustomItems() { resetMessages() const ok = window.confirm('현재 검색 조건에 맞는 미사용 커스텀 이미지를 모두 삭제할까요?') if (!ok) return try { const data = await api.deleteAdminUnusedCustomItems({ q: customItemQuery.value }) await refreshCustomItems() success.value = `${data.deletedCount || 0}개의 미사용 사용자 업로드 이미지를 삭제했어요.` } catch (e) { error.value = '미사용 커스텀 이미지 일괄 삭제에 실패했어요.' } } async function saveCustomItemModalLabel() { const item = modalTargetCustomItem.value const nextLabel = customItemModalDraftLabel.value.trim().slice(0, 60) if (!item || !nextLabel || nextLabel === item.label || customItemModalLabelSaving.value) return try { customItemModalLabelSaving.value = true const data = await api.updateAdminCustomItemLabel(item.id, { label: nextLabel, sourceType: item.sourceType }) item.label = data.item?.label || nextLabel customItemModalDraftLabel.value = item.label customItems.value = customItems.value.map((entry) => (entry.id === item.id ? { ...entry, label: item.label } : entry)) toast.success('아이템 이름을 변경했어요.') } catch (e) { error.value = '아이템 이름 변경에 실패했어요.' } finally { customItemModalLabelSaving.value = false } } async function promoteCustomItem(item) { resetMessages() if (!customItemModalTargetGameId.value) { error.value = '추가할 게임을 먼저 선택해주세요.' return } try { item.isPromoting = true await api.promoteAdminCustomItem(item.id, { gameId: customItemModalTargetGameId.value }) const targetGameName = games.value.find((game) => game.id === customItemModalTargetGameId.value)?.name || customItemModalTargetGameId.value if (selectedGameId.value === customItemModalTargetGameId.value) await loadGame() closeCustomItemModal() success.value = `"${item.label}" 이미지를 ${targetGameName} 템플릿으로 추가했어요.` } catch (e) { error.value = '선택한 이미지를 템플릿으로 추가하지 못했어요.' } finally { item.isPromoting = false } } return { submitCustomItemSearch, toggleCustomItemOrphanOnly, changeCustomItemLimit, moveCustomItemPage, pushCustomItemModalHistoryState, openCustomItemModal, closeCustomItemModal, openCustomItemDeleteModal, closeCustomItemDeleteModal, jumpToGameAdmin, removeCustomItem, removeUnusedCustomItems, saveCustomItemModalLabel, promoteCustomItem, } }