<script setup>
import { computed, ref, watch } from 'vue'
import { router } from '@inertiajs/vue3'
import { VueDraggable } from 'vue-draggable-plus'

const MASTER_ID = 'master'

const props = defineProps({
    songId: {
        type: Number,
        required: true,
    },
    arrangements: {
        type: Array,
        required: true,
    },
    availableGroups: {
        type: Array,
        required: true,
    },
    selectedArrangementId: {
        type: [Number, String],
        default: null,
    },
})

const emit = defineEmits(['arrangement-selected', 'arrangements-changed'])

// Virtual MASTER arrangement — always first, computed from availableGroups
const masterArrangement = computed(() => ({
    id: MASTER_ID,
    name: 'MASTER',
    is_default: false,
    is_master: true,
    groups: props.availableGroups.map((g) => ({ ...g })),
}))

// All arrangements with MASTER prepended
const allArrangements = computed(() => [
    masterArrangement.value,
    ...props.arrangements,
])

const selectedId = ref(
    props.selectedArrangementId ?? props.arrangements.find((item) => item.is_default)?.id ?? props.arrangements[0]?.id ?? MASTER_ID,
)

const isMasterSelected = computed(() => selectedId.value === MASTER_ID)

const arrangementGroups = ref([])
const poolGroups = ref([])

const selectedArrangement = computed(() =>
    allArrangements.value.find((arrangement) => arrangement.id === selectedId.value)
    ?? allArrangements.value.find((arrangement) => arrangement.id === Number(selectedId.value))
    ?? null,
)

watch(
    () => props.availableGroups,
    (groups) => {
        poolGroups.value = groups.map((group) => ({ ...group }))
    },
    { immediate: true, deep: true },
)

watch(
    selectedArrangement,
    (arrangement) => {
        if (arrangement?.groups) {
            arrangementGroups.value = arrangement.groups.map((group) => ({ ...group }))
        } else if (arrangement?.arrangement_groups) {
            arrangementGroups.value = arrangement.arrangement_groups
                .map((ag) => props.availableGroups.find((g) => g.id === ag.label_id))
                .filter(Boolean)
                .map((g) => ({ ...g }))
        } else {
            arrangementGroups.value = []
        }
    },
    { immediate: true },
)

watch(
    selectedId,
    (arrangementId) => {
        emit('arrangement-selected', arrangementId === MASTER_ID ? null : Number(arrangementId))
    },
)

const groupPillStyle = (group) => ({
    backgroundColor: group.color,
})

const pendingAutoSelect = ref(false)

watch(
    () => props.arrangements.length,
    (newLen, oldLen) => {
        if (pendingAutoSelect.value && newLen > oldLen) {
            const newest = props.arrangements.reduce((a, b) => a.id > b.id ? a : b)
            selectedId.value = newest.id
            pendingAutoSelect.value = false
        }
    },
)

function addArrangement() {
    const name = window.prompt('Name des neuen Arrangements')
    if (!name) return
    pendingAutoSelect.value = true
    router.post(`/songs/${props.songId}/arrangements`, { name }, {
        preserveScroll: true,
        onSuccess: () => {
            emit('arrangements-changed')
        },
    })
}

function cloneArrangement() {
    if (!selectedArrangement.value) return

    // Cloning from MASTER = creating a new arrangement (store() already uses all groups in master order)
    if (isMasterSelected.value) {
        const name = window.prompt('Name des neuen Arrangements', 'MASTER Kopie')
        if (!name) return
        pendingAutoSelect.value = true
        router.post(`/songs/${props.songId}/arrangements`, { name }, {
            preserveScroll: true,
            onSuccess: () => {
                emit('arrangements-changed')
            },
        })
        return
    }

    const name = window.prompt('Name des neuen Arrangements', `${selectedArrangement.value.name} Kopie`)
    if (!name) return
    pendingAutoSelect.value = true
    router.post(`/arrangements/${selectedArrangement.value.id}/clone`, { name }, {
        preserveScroll: true,
        onSuccess: () => {
            emit('arrangements-changed')
        },
    })
}

function addGroupFromPool(group) {
    if (isMasterSelected.value) return
    arrangementGroups.value.push({ ...group })
    saveArrangement()
}

function removeGroupAt(index) {
    if (isMasterSelected.value) return
    arrangementGroups.value.splice(index, 1)
    saveArrangement()
}

function saveArrangement() {
    if (!selectedArrangement.value || isMasterSelected.value) {
        return
    }

    router.put(
        `/arrangements/${selectedArrangement.value.id}`,
        {
            groups: arrangementGroups.value.map((group, index) => ({
                section_id: group.section_id ?? group.id,
                order: index + 1,
            })),
        },
        {
            preserveScroll: true,
            preserveState: true,
        },
    )
}

function deleteArrangement() {
    if (!selectedArrangement.value || isMasterSelected.value) {
        return
    }

    router.delete(`/arrangements/${selectedArrangement.value.id}`, {
        preserveScroll: true,
        onSuccess: () => {
            emit('arrangements-changed')
        },
    })
}
</script>

<template>
    <div data-testid="arrangement-configurator" class="space-y-4 rounded-lg border border-gray-200 bg-white p-4">
        <div class="flex flex-wrap items-end gap-3">
            <div class="min-w-64 flex-1">
                <label
                    for="arrangement-select"
                    class="mb-1 block text-sm font-medium text-gray-700"
                >
                    Arrangement
                </label>
                <select
                    data-testid="arrangement-select"
                    id="arrangement-select"
                    v-model="selectedId"
                    class="block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500"
                >
                    <option
                        v-for="arrangement in allArrangements"
                        :key="arrangement.id"
                        :value="arrangement.id"
                    >
                        {{ arrangement.name }}{{ arrangement.is_default ? ' (Standard)' : '' }}
                    </option>
                </select>
            </div>

            <button
                data-testid="arrangement-add-button"
                type="button"
                class="rounded-md bg-blue-600 px-4 py-2 text-sm font-semibold text-white shadow hover:bg-blue-700"
                @click="addArrangement"
            >
                Hinzufügen
            </button>

            <button
                data-testid="arrangement-clone-button"
                type="button"
                class="rounded-md bg-slate-700 px-4 py-2 text-sm font-semibold text-white shadow hover:bg-slate-800"
                @click="cloneArrangement"
            >
                Klonen
            </button>

            <button
                data-testid="arrangement-delete-button"
                type="button"
                class="rounded-md bg-red-600 px-4 py-2 text-sm font-semibold text-white shadow hover:bg-red-700 disabled:cursor-not-allowed disabled:opacity-40"
                :disabled="isMasterSelected"
                @click="deleteArrangement"
            >
                Löschen
            </button>
        </div>

        <div class="grid gap-4 lg:grid-cols-2">
            <div class="space-y-1">
                <h4 class="text-xs font-semibold uppercase tracking-wide text-gray-500">
                    Verfügbare Gruppen
                </h4>

                <VueDraggable
                    v-model="poolGroups"
                    :group="{ name: 'song-groups', pull: isMasterSelected ? false : 'clone', put: false }"
                    :sort="false"
                    :disabled="isMasterSelected"
                    ghost-class="drag-ghost"
                    chosen-class="drag-chosen"
                    drag-class="drag-active"
                    class="flex flex-wrap gap-1.5 rounded-lg border border-dashed border-gray-300 bg-gray-50 p-2"
                    :class="{ 'opacity-50': isMasterSelected }"
                >
                    <span
                        v-for="group in poolGroups"
                        :key="group.id"
                        class="inline-flex rounded-full px-2.5 py-0.5 text-xs font-semibold text-white transition-opacity hover:opacity-80"
                        :class="isMasterSelected ? 'cursor-default' : 'cursor-grab'"
                        :style="groupPillStyle(group)"
                        @click="addGroupFromPool(group)"
                    >
                        {{ group.name }}
                    </span>
                </VueDraggable>
            </div>

            <div class="space-y-1">
                <h4 class="text-xs font-semibold uppercase tracking-wide text-gray-500">
                    Gruppenfolge
                    <span v-if="isMasterSelected" class="ml-1 text-[10px] font-normal normal-case text-gray-400">(nicht editierbar)</span>
                </h4>

                <VueDraggable
                    v-model="arrangementGroups"
                    :group="{ name: 'song-groups', pull: true, put: !isMasterSelected }"
                    :disabled="isMasterSelected"
                    ghost-class="drag-ghost"
                    chosen-class="drag-chosen"
                    drag-class="drag-active"
                    class="flex min-h-10 flex-wrap gap-1.5 rounded-lg border border-gray-200 bg-gray-50 p-2"
                    :class="{ 'opacity-60': isMasterSelected }"
                    @end="saveArrangement"
                >
                    <span
                        v-for="(group, index) in arrangementGroups"
                        :key="`${group.id}-${index}`"
                        class="inline-flex items-center gap-1 rounded-full py-0.5 pl-2.5 text-xs font-semibold text-white"
                        :class="isMasterSelected ? 'cursor-default pr-2.5' : 'cursor-grab pr-1'"
                        :style="groupPillStyle(group)"
                    >
                        {{ group.name }}
                        <button
                            v-if="!isMasterSelected"
                            data-testid="arrangement-remove-button"
                            type="button"
                            class="ml-0.5 flex h-4 w-4 items-center justify-center rounded-full text-white/70 transition-colors hover:bg-white/20 hover:text-white"
                            @click.stop="removeGroupAt(index)"
                        >
                            ×
                        </button>
                    </span>
                </VueDraggable>
            </div>
        </div>
    </div>
</template>

<style scoped>
:deep(.drag-ghost) {
    opacity: 0.4;
    ring: 2px solid white;
    box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.8), 0 0 0 4px rgba(99, 102, 241, 0.6);
    border-radius: 9999px;
}

:deep(.drag-chosen) {
    opacity: 0.7;
}

:deep(.drag-active) {
    opacity: 1 !important;
    transform: scale(1.1);
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3), 0 0 0 2px rgba(255, 255, 255, 0.8);
    border-radius: 9999px;
    z-index: 50;
}
</style>
