import axios from 'axios'
import Sortable from 'sortablejs'

export function menuEditor(existingItems = []) {
    let _ctr = 0
    const _items = existingItems.map(item => ({
        ...item,
        _id: ++_ctr,
        children: (item.children ?? []).map(child => ({ ...child, _id: ++_ctr })),
    }))

    return {
        items: _items,
        newLabel: '',
        newUrl: '',
        newTarget: '_self',
        _counter: _ctr,
        menuSaving: false,
        menuSaved: false,
        menuMessage: '',

        // Post/page picker
        pickerTab: 'custom',
        pickerSearch: '',
        pickerResults: [],
        pickerLoading: false,
        pickerTimer: null,

        init() {
            this.$nextTick(() => this.initSortable())
        },

        initSortable() {
            const container = this.$refs.menuTree
            if (!container) return

            Sortable.create(container, {
                handle: '.drag-handle',
                animation: 150,
                ghostClass: 'opacity-40',
                onEnd: (evt) => {
                    const moved = this.items.splice(evt.oldIndex, 1)[0]
                    this.items.splice(evt.newIndex, 0, moved)
                },
            })

            // Init nested sortable for children
            this.$nextTick(() => this.initChildSortables())
        },

        initChildSortables() {
            const childContainers = this.$el.querySelectorAll('[data-children]')
            childContainers.forEach(el => {
                const parentId = parseInt(el.dataset.children)
                if (el._sortable) return
                el._sortable = Sortable.create(el, {
                    handle: '.drag-handle',
                    animation: 150,
                    ghostClass: 'opacity-40',
                    onEnd: (evt) => {
                        const parent = this.items.find(i => i._id === parentId)
                        if (!parent) return
                        const moved = parent.children.splice(evt.oldIndex, 1)[0]
                        parent.children.splice(evt.newIndex, 0, moved)
                    },
                })
            })
        },

        removeItem(index) {
            this.items.splice(index, 1)
        },

        removeChild(parentIndex, childIndex) {
            this.items[parentIndex].children.splice(childIndex, 1)
        },

        promoteChild(parentIndex, childIndex) {
            const child = this.items[parentIndex].children.splice(childIndex, 1)[0]
            this.items.splice(parentIndex + 1, 0, { ...child, children: child.children ?? [] })
            this.$nextTick(() => this.initChildSortables())
        },

        demoteItem(index) {
            if (index === 0) return
            const item = this.items[index]
            if (item.children && item.children.length > 0) return
            this.items.splice(index, 1)
            if (!this.items[index - 1].children) this.items[index - 1].children = []
            this.items[index - 1].children.push({ ...item, children: [] })
            this.$nextTick(() => this.initChildSortables())
        },

        async searchPicker() {
            const type = this.pickerTab
            if (type === 'custom') return
            clearTimeout(this.pickerTimer)
            this.pickerTimer = setTimeout(async () => {
                this.pickerLoading = true
                try {
                    const { data } = await axios.get(`/admin/posts/${type}`, {
                        params: { search: this.pickerSearch, per_page: 20 },
                        headers: { Accept: 'application/json' },
                    })
                    this.pickerResults = data.data ?? []
                } catch {
                    this.pickerResults = []
                } finally {
                    this.pickerLoading = false
                }
            }, 300)
        },

        async switchTab(tab) {
            this.pickerTab = tab
            this.pickerSearch = ''
            this.pickerResults = []
            if (tab !== 'custom') await this.searchPicker()
        },

        addPostItem(post) {
            this.items.push({
                _id: ++this._counter,
                label: post.title,
                url: '/' + post.type + '/' + post.slug,
                type: this.pickerTab,
                target: this.newTarget,
                sort_order: this.items.length,
                children: [],
            })
            this.$nextTick(() => this.initChildSortables())
        },

        addItem() {
            if (!this.newLabel.trim()) return
            this.items.push({
                _id: ++this._counter,
                label: this.newLabel,
                url: this.newUrl || '#',
                type: 'custom',
                target: this.newTarget,
                sort_order: this.items.length,
                children: [],
            })
            this.newLabel = ''
            this.newUrl = ''
            this.$nextTick(() => this.initChildSortables())
        },

        async saveMenu(event) {
            const form = event.target
            this.menuSaving = true
            this.menuMessage = ''
            this.menuSaved = false

            const formData = new FormData(form)

            try {
                const { data } = await axios.post(form.action, formData, {
                    headers: {
                        'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content,
                        Accept: 'application/json',
                    },
                })
                this.menuMessage = data.message ?? 'Menu saved.'
                this.menuSaved = true
                setTimeout(() => { this.menuSaved = false; this.menuMessage = '' }, 3000)
            } catch (e) {
                this.menuMessage = e.response?.data?.message ?? 'Error saving menu.'
                this.menuSaved = false
            } finally {
                this.menuSaving = false
            }
        },
    }
}
