<script setup>
import { computed, ref, watch, onMounted, onUnmounted } from 'vue'
import { useDebounceFn } from '@vueuse/core'
import ArrangementConfigurator from '@/Components/ArrangementConfigurator.vue'

const props = defineProps({
    show: {
        type: Boolean,
        default: false,
    },
    songId: {
        type: Number,
        default: null,
    },
})

const emit = defineEmits(['close', 'updated'])

/* ── State ── */

const loading = ref(false)
const error = ref(null)
const songData = ref(null)
const sectionDrafts = ref({})

const title = ref('')
const ccliId = ref('')
const copyrightText = ref('')
const showAddSectionForm = ref(false)
const newSectionLabel = ref('')
const newSectionText = ref('')

const saving = ref(false)
const saved = ref(false)
let savedTimeout = null
const sectionSaveDebouncers = new Map()

/* ── Save status ── */

function startSaving() {
    saving.value = true
    saved.value = false
}

function finishSaving() {
    saving.value = false
    saved.value = true

    if (savedTimeout) clearTimeout(savedTimeout)
    savedTimeout = setTimeout(() => {
        saved.value = false
    }, 2000)
}

function stopSaving() {
    saving.value = false
}

/* ── Data fetching ── */

function slidesToText(slides = [], key) {
    return slides
        .map((slide) => slide[key] ?? '')
        .filter((text) => text !== '')
        .join('\n\n')
}

function sectionKey(group) {
    return group.section_id ?? group.id
}

function setSectionDrafts(data) {
    const drafts = {}

    ;(data?.groups ?? []).forEach((group) => {
        drafts[sectionKey(group)] = {
            text: slidesToText(group.slides, 'text_content'),
            translated: slidesToText(group.slides, 'text_content_translated'),
        }
    })

    sectionDrafts.value = drafts
}

function draftFor(group) {
    const key = sectionKey(group)

    if (!sectionDrafts.value[key]) {
        sectionDrafts.value[key] = { text: '', translated: '' }
    }

    return sectionDrafts.value[key]
}

const fetchSong = async () => {
    if (!props.songId) return

    loading.value = true
    error.value = null

    try {
        const response = await fetch(`/api/songs/${props.songId}`, {
            headers: {
                Accept: 'application/json',
                'X-Requested-With': 'XMLHttpRequest',
            },
            credentials: 'same-origin',
        })

        if (!response.ok) {
            throw new Error('Song konnte nicht geladen werden.')
        }

        const json = await response.json()
        songData.value = json.data
        setSectionDrafts(json.data)

        title.value = json.data.title ?? ''
        ccliId.value = json.data.ccli_id ?? ''
        copyrightText.value = json.data.copyright_text ?? ''
    } catch (e) {
        error.value = e.message
    } finally {
        loading.value = false
    }
}

watch(
    () => props.show,
    (isVisible) => {
        if (isVisible && props.songId) {
            fetchSong()
        }

        if (!isVisible) {
            songData.value = null
            sectionDrafts.value = {}
            error.value = null
            showAddSectionForm.value = false
            newSectionLabel.value = ''
            newSectionText.value = ''
        }
    },
)

/* ── Auto-save metadata (fetch-based, 500ms debounce for text) ── */

const performSave = async (data) => {
    if (!props.songId) return

    startSaving()

    try {
        const csrfToken = document.querySelector('meta[name="csrf-token"]')?.content || ''

        const response = await fetch(`/api/songs/${props.songId}`, {
            method: 'PUT',
            headers: {
                'Content-Type': 'application/json',
                Accept: 'application/json',
                'X-Requested-With': 'XMLHttpRequest',
                'X-CSRF-TOKEN': csrfToken,
            },
            credentials: 'same-origin',
            body: JSON.stringify(data),
        })

        if (!response.ok) {
            throw new Error('Speichern fehlgeschlagen')
        }

        finishSaving()

        emit('updated')
    } catch {
        stopSaving()
    }
}

const buildPayload = () => ({
    title: title.value,
    ccli_id: ccliId.value || null,
    copyright_text: copyrightText.value || null,
})

// 500ms debounce for text inputs
const debouncedSave = useDebounceFn((data) => {
    performSave(data)
}, 500)

const onTextInput = () => {
    debouncedSave(buildPayload())
}

// Immediate save on blur (cancel pending debounce)
const onFieldBlur = () => {
    debouncedSave.cancel?.()
    performSave(buildPayload())
}

/* ── Arrangement props ── */

const arrangements = computed(() => {
    if (!songData.value?.arrangements) return []

    return songData.value.arrangements.map((arr) => ({
        id: arr.id,
        name: arr.name,
        is_default: arr.is_default,
        groups: arr.arrangement_groups.map((ag) => {
            const group = songData.value.groups.find((g) => g.id === (ag.section_id ?? ag.label_id))

            return {
                id: ag.section_id ?? ag.label_id,
                section_id: ag.section_id ?? ag.label_id,
                label_id: ag.label_id,
                name: group?.name ?? 'Unbekannt',
                color: group?.color ?? '#6b7280',
                order: ag.order,
            }
        }),
    }))
})

const availableGroups = computed(() => {
    if (!songData.value?.groups) return []

    return songData.value.groups.map((group) => ({
        id: group.id,
        section_id: group.section_id ?? group.id,
        label_id: group.label_id,
        name: group.name,
        color: group.color,
    }))
})

const sectionLabelOptions = computed(() => {
    if (!songData.value?.groups) return []

    return [...new Set(songData.value.groups.map((group) => group.name).filter(Boolean))]
})

/* ── Section editing ── */

function splitSectionText(value) {
    const trimmed = (value ?? '').replace(/\r\n/g, '\n').replace(/\s+$/u, '')
    const blocks = trimmed
        .split(/\n\s*\n+/u)
        .map((block) => block.trim())
        .filter((block) => block !== '')

    return blocks.length ? blocks : ['']
}

function buildSectionSlides(sectionId) {
    const draft = sectionDrafts.value[sectionId] ?? { text: '', translated: '' }
    const textBlocks = splitSectionText(draft.text)
    const translatedBlocks = (draft.translated ?? '').trim() === '' ? [] : splitSectionText(draft.translated)

    return textBlocks.map((text, index) => ({
        text_content: text,
        text_content_translated: translatedBlocks[index] ?? null,
    }))
}

async function saveSection(sectionId) {
    if (!props.songId || !sectionDrafts.value[sectionId]) return

    startSaving()

    try {
        const csrfToken = document.querySelector('meta[name="csrf-token"]')?.content || ''
        const response = await fetch(route('songs.sections.update', [props.songId, sectionId]), {
            method: 'PATCH',
            headers: {
                'Content-Type': 'application/json',
                Accept: 'application/json',
                'X-Requested-With': 'XMLHttpRequest',
                'X-CSRF-TOKEN': csrfToken,
            },
            credentials: 'same-origin',
            body: JSON.stringify({
                slides: buildSectionSlides(sectionId),
            }),
        })

        if (!response.ok) {
            throw new Error('Sektion konnte nicht gespeichert werden.')
        }

        const json = await response.json()
        songData.value = json.data
        setSectionDrafts(json.data)
        finishSaving()
        emit('updated')
    } catch {
        stopSaving()
    }
}

function onSectionInput(sectionId) {
    if (!sectionSaveDebouncers.has(sectionId)) {
        sectionSaveDebouncers.set(sectionId, useDebounceFn(() => {
            saveSection(sectionId)
        }, 600))
    }

    sectionSaveDebouncers.get(sectionId)()
}

function onSectionBlur(sectionId) {
    sectionSaveDebouncers.get(sectionId)?.cancel?.()
    saveSection(sectionId)
}

async function deleteSection(sectionId) {
    if (!window.confirm('Möchtest Du diese Sektion wirklich löschen?')) return

    startSaving()

    try {
        const csrfToken = document.querySelector('meta[name="csrf-token"]')?.content || ''
        const response = await fetch(route('songs.sections.destroy', [props.songId, sectionId]), {
            method: 'DELETE',
            headers: {
                Accept: 'application/json',
                'X-Requested-With': 'XMLHttpRequest',
                'X-CSRF-TOKEN': csrfToken,
            },
            credentials: 'same-origin',
        })

        if (!response.ok) {
            throw new Error('Sektion konnte nicht gelöscht werden.')
        }

        const json = await response.json()
        songData.value = json.data
        setSectionDrafts(json.data)
        finishSaving()
        emit('updated')
    } catch {
        stopSaving()
    }
}

async function addSection() {
    if (!props.songId || !newSectionLabel.value.trim()) return

    startSaving()

    try {
        const csrfToken = document.querySelector('meta[name="csrf-token"]')?.content || ''
        const response = await fetch(route('songs.sections.store', props.songId), {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                Accept: 'application/json',
                'X-Requested-With': 'XMLHttpRequest',
                'X-CSRF-TOKEN': csrfToken,
            },
            credentials: 'same-origin',
            body: JSON.stringify({
                label_name: newSectionLabel.value,
                slides: splitSectionText(newSectionText.value).map((text) => ({ text_content: text })),
            }),
        })

        if (!response.ok) {
            throw new Error('Sektion konnte nicht hinzugefügt werden.')
        }

        newSectionLabel.value = ''
        newSectionText.value = ''
        showAddSectionForm.value = false

        await fetchSong()
        finishSaving()
        emit('updated')
    } catch {
        stopSaving()
    }
}

/* ── Close handling ── */

const closeOnEscape = (e) => {
    if (e.key === 'Escape' && props.show) {
        emit('close')
    }
}

const closeOnBackdrop = (e) => {
    if (e.target === e.currentTarget) {
        emit('close')
    }
}

onMounted(() => {
    document.addEventListener('keydown', closeOnEscape)
})

onUnmounted(() => {
    document.removeEventListener('keydown', closeOnEscape)
})
</script>

<template>
    <Teleport to="body">
        <Transition
            enter-active-class="transition duration-200 ease-out"
            enter-from-class="opacity-0"
            enter-to-class="opacity-100"
            leave-active-class="transition duration-150 ease-in"
            leave-from-class="opacity-100"
            leave-to-class="opacity-0"
        >
            <div
                v-if="show"
                class="fixed inset-0 z-50 flex items-start justify-center overflow-y-auto bg-black/50 p-4 sm:p-8"
                @click="closeOnBackdrop"
            >
                <div data-testid="song-edit-modal" class="relative w-full max-w-4xl rounded-xl bg-white shadow-2xl">
                    <!-- Header -->
                    <div class="flex items-center justify-between border-b border-gray-200 px-6 py-4">
                        <div class="flex items-center gap-3">
                            <div class="flex h-10 w-10 items-center justify-center rounded-lg bg-amber-100">
                                <svg
                                    class="h-5 w-5 text-amber-600"
                                    fill="none"
                                    viewBox="0 0 24 24"
                                    stroke="currentColor"
                                    stroke-width="2"
                                >
                                    <path
                                        stroke-linecap="round"
                                        stroke-linejoin="round"
                                        d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"
                                    />
                                </svg>
                            </div>

                            <div>
                                <h2 class="text-xl font-bold text-gray-900">
                                    Song bearbeiten
                                </h2>

                                <p class="text-sm text-gray-500">
                                    Metadaten und Arrangements verwalten
                                </p>
                            </div>
                        </div>

                        <div class="flex items-center gap-3">
                            <!-- Save status indicator -->
                            <Transition
                                enter-active-class="transition duration-200 ease-out"
                                enter-from-class="opacity-0 translate-y-1"
                                enter-to-class="opacity-100 translate-y-0"
                                leave-active-class="transition duration-150 ease-in"
                                leave-from-class="opacity-100"
                                leave-to-class="opacity-0"
                            >
                                <span
                                    v-if="saving"
                                    class="inline-flex items-center gap-1.5 text-sm text-gray-400"
                                >
                                    <svg
                                        class="h-4 w-4 animate-spin"
                                        fill="none"
                                        viewBox="0 0 24 24"
                                    >
                                        <circle
                                            class="opacity-25"
                                            cx="12"
                                            cy="12"
                                            r="10"
                                            stroke="currentColor"
                                            stroke-width="4"
                                        />
                                        <path
                                            class="opacity-75"
                                            fill="currentColor"
                                            d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"
                                        />
                                    </svg>
                                    Speichert…
                                </span>

                                <span
                                    v-else-if="saved"
                                    class="inline-flex items-center gap-1.5 text-sm text-emerald-600"
                                >
                                    <svg
                                        class="h-4 w-4"
                                        fill="none"
                                        viewBox="0 0 24 24"
                                        stroke="currentColor"
                                        stroke-width="2"
                                    >
                                        <path
                                            stroke-linecap="round"
                                            stroke-linejoin="round"
                                            d="M5 13l4 4L19 7"
                                        />
                                    </svg>
                                    Gespeichert
                                </span>
                            </Transition>

                            <button
                                data-testid="song-edit-modal-close-button"
                                type="button"
                                class="rounded-lg p-2 text-gray-400 hover:bg-gray-100 hover:text-gray-600"
                                @click="emit('close')"
                            >
                                <svg
                                    class="h-5 w-5"
                                    fill="none"
                                    viewBox="0 0 24 24"
                                    stroke="currentColor"
                                    stroke-width="2"
                                >
                                    <path
                                        stroke-linecap="round"
                                        stroke-linejoin="round"
                                        d="M6 18L18 6M6 6l12 12"
                                    />
                                </svg>
                            </button>
                        </div>
                    </div>

                    <!-- Loading State -->
                    <div
                        v-if="loading"
                        class="flex items-center justify-center py-16"
                    >
                        <svg
                            class="h-8 w-8 animate-spin text-amber-500"
                            fill="none"
                            viewBox="0 0 24 24"
                        >
                            <circle
                                class="opacity-25"
                                cx="12"
                                cy="12"
                                r="10"
                                stroke="currentColor"
                                stroke-width="4"
                            />
                            <path
                                class="opacity-75"
                                fill="currentColor"
                                d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"
                            />
                        </svg>
                        <span class="ml-3 text-gray-600">Song wird geladen…</span>
                    </div>

                    <!-- Error State -->
                    <div
                        v-else-if="error"
                        class="px-6 py-16 text-center"
                    >
                        <div class="mx-auto mb-4 flex h-12 w-12 items-center justify-center rounded-full bg-red-100">
                            <svg
                                class="h-6 w-6 text-red-600"
                                fill="none"
                                viewBox="0 0 24 24"
                                stroke="currentColor"
                                stroke-width="2"
                            >
                                <path
                                    stroke-linecap="round"
                                    stroke-linejoin="round"
                                    d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L4.082 16.5c-.77.833.192 2.5 1.732 2.5z"
                                />
                            </svg>
                        </div>

                        <p class="text-red-600">{{ error }}</p>

                        <button
                            data-testid="song-edit-modal-error-close-button"
                            type="button"
                            class="mt-4 rounded-md bg-gray-200 px-4 py-2 text-sm font-semibold text-gray-700 hover:bg-gray-300"
                            @click="emit('close')"
                        >
                            Schließen
                        </button>
                    </div>

                    <!-- Content -->
                    <div
                        v-else-if="songData"
                        class="max-h-[80vh] overflow-y-auto"
                    >
                        <!-- Metadata Fields -->
                        <div class="border-b border-gray-100 px-6 py-5">
                            <h3 class="mb-4 text-sm font-semibold uppercase tracking-wide text-gray-500">
                                Metadaten
                            </h3>

                            <div class="grid gap-4 sm:grid-cols-2">
                                <div class="sm:col-span-2">
                                    <label
                                        for="song-edit-title"
                                        class="mb-1 block text-sm font-medium text-gray-700"
                                    >
                                        Titel
                                    </label>
                                    <input
                                        data-testid="song-edit-modal-title-input"
                                        id="song-edit-title"
                                        v-model="title"
                                        type="text"
                                        class="block w-full rounded-md border-gray-300 shadow-sm focus:border-amber-500 focus:ring-amber-500"
                                        placeholder="Songtitel eingeben…"
                                        @input="onTextInput"
                                        @blur="onFieldBlur"
                                    >
                                </div>

                                <div>
                                    <label
                                        for="song-edit-ccli"
                                        class="mb-1 block text-sm font-medium text-gray-700"
                                    >
                                        CCLI-ID
                                    </label>
                                    <input
                                        data-testid="song-edit-modal-ccli-input"
                                        id="song-edit-ccli"
                                        v-model="ccliId"
                                        type="text"
                                        class="block w-full rounded-md border-gray-300 shadow-sm focus:border-amber-500 focus:ring-amber-500"
                                        placeholder="z.B. 123456"
                                        @input="onTextInput"
                                        @blur="onFieldBlur"
                                    >
                                </div>

                                <div class="self-end pb-2 text-sm text-gray-400">
                                    <span
                                        v-if="songData.has_translation"
                                        class="inline-flex items-center gap-1 text-emerald-600"
                                    >
                                        <svg
                                            class="h-4 w-4"
                                            fill="none"
                                            viewBox="0 0 24 24"
                                            stroke="currentColor"
                                            stroke-width="2"
                                        >
                                            <path
                                                stroke-linecap="round"
                                                stroke-linejoin="round"
                                                d="M3 5h12M9 3v2m1.048 9.5A18.022 18.022 0 016.412 9m6.088 9h7M11 21l5-10 5 10M12.751 5C11.783 10.77 8.07 15.61 3 18.129"
                                            />
                                        </svg>
                                        Übersetzung vorhanden
                                    </span>

                                    <span
                                        v-else
                                        class="text-gray-400"
                                    >
                                        Keine Übersetzung
                                    </span>
                                </div>

                                <div class="sm:col-span-2">
                                    <label
                                        for="song-edit-copyright"
                                        class="mb-1 block text-sm font-medium text-gray-700"
                                    >
                                        Copyright-Text
                                    </label>
                                    <textarea
                                        data-testid="song-edit-modal-copyright-textarea"
                                        id="song-edit-copyright"
                                        v-model="copyrightText"
                                        rows="3"
                                        class="block w-full rounded-md border-gray-300 shadow-sm focus:border-amber-500 focus:ring-amber-500"
                                        placeholder="Copyright-Informationen…"
                                        @input="onTextInput"
                                        @blur="onFieldBlur"
                                    />
                                </div>
                            </div>
                        </div>

                        <!-- Section editing -->
                        <div class="border-b border-gray-100 px-6 py-5">
                            <div class="mb-4 flex items-center justify-between gap-3">
                                <div>
                                    <h3 class="text-sm font-semibold uppercase tracking-wide text-gray-500">
                                        Sektionen
                                    </h3>

                                    <p class="mt-1 text-sm text-gray-500">
                                        Leerzeilen trennen einzelne Folien. Änderungen speichern automatisch.
                                    </p>
                                </div>

                                <button
                                    data-testid="section-add-button"
                                    type="button"
                                    class="rounded-md bg-amber-500 px-4 py-2 text-sm font-semibold text-white shadow hover:bg-amber-600"
                                    @click="showAddSectionForm = !showAddSectionForm"
                                >
                                    Neue Sektion
                                </button>
                            </div>

                            <form
                                v-if="showAddSectionForm"
                                class="mb-5 rounded-lg border border-amber-200 bg-amber-50 p-4"
                                @submit.prevent="addSection"
                            >
                                <div class="grid gap-4 sm:grid-cols-3">
                                    <div>
                                        <label for="section-add-label" class="mb-1 block text-sm font-medium text-gray-700">
                                            Name
                                        </label>
                                        <input
                                            data-testid="section-add-label-input"
                                            id="section-add-label"
                                            v-model="newSectionLabel"
                                            list="section-label-options"
                                            type="text"
                                            class="block w-full rounded-md border-gray-300 shadow-sm focus:border-amber-500 focus:ring-amber-500"
                                            placeholder="z.B. Strophe 3"
                                            required
                                        >
                                        <datalist id="section-label-options">
                                            <option
                                                v-for="labelName in sectionLabelOptions"
                                                :key="labelName"
                                                :value="labelName"
                                            />
                                        </datalist>
                                    </div>

                                    <div class="sm:col-span-2">
                                        <label for="section-add-text" class="mb-1 block text-sm font-medium text-gray-700">
                                            Text
                                        </label>
                                        <textarea
                                            data-testid="section-add-text-input"
                                            id="section-add-text"
                                            v-model="newSectionText"
                                            rows="4"
                                            class="block w-full rounded-md border-gray-300 shadow-sm focus:border-amber-500 focus:ring-amber-500"
                                            placeholder="Folientext eingeben…"
                                        />
                                    </div>
                                </div>

                                <div class="mt-3 flex justify-end gap-2">
                                    <button
                                        type="button"
                                        class="rounded-md px-3 py-2 text-sm font-semibold text-gray-600 hover:bg-white/70"
                                        @click="showAddSectionForm = false"
                                    >
                                        Abbrechen
                                    </button>

                                    <button
                                        data-testid="section-add-submit"
                                        type="submit"
                                        class="rounded-md bg-gray-900 px-4 py-2 text-sm font-semibold text-white shadow hover:bg-gray-800"
                                    >
                                        Hinzufügen
                                    </button>
                                </div>
                            </form>

                            <div class="space-y-4">
                                <div
                                    v-for="group in songData.groups"
                                    :key="group.section_id ?? group.id"
                                    data-testid="section-block"
                                    class="rounded-lg border border-gray-200 bg-white p-4 shadow-sm"
                                >
                                    <div class="mb-3 flex items-center justify-between gap-3">
                                        <span
                                            class="inline-flex rounded-full px-3 py-1 text-sm font-semibold text-white shadow-sm"
                                            :style="{ backgroundColor: group.color ?? '#6b7280' }"
                                        >
                                            {{ group.name }}
                                        </span>

                                        <button
                                            data-testid="section-delete-button"
                                            type="button"
                                            class="rounded-md p-2 text-red-500 hover:bg-red-50 hover:text-red-700"
                                            title="Sektion löschen"
                                            @click="deleteSection(group.section_id ?? group.id)"
                                        >
                                            <svg class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
                                                <path stroke-linecap="round" stroke-linejoin="round" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6M9 7h6m2 0H7m3-3h4a1 1 0 011 1v2H9V5a1 1 0 011-1z" />
                                            </svg>
                                        </button>
                                    </div>

                                    <div :class="songData.has_translation ? 'grid gap-4 lg:grid-cols-2' : ''">
                                        <div>
                                            <label class="mb-1 block text-sm font-medium text-gray-700">
                                                Originaltext
                                            </label>
                                            <textarea
                                                data-testid="section-text-input"
                                                v-model="draftFor(group).text"
                                                rows="6"
                                                class="block w-full rounded-md border-gray-300 shadow-sm focus:border-amber-500 focus:ring-amber-500"
                                                placeholder="Folientext…"
                                                @input="onSectionInput(group.section_id ?? group.id)"
                                                @blur="onSectionBlur(group.section_id ?? group.id)"
                                            />
                                        </div>

                                        <div v-if="songData.has_translation">
                                            <label class="mb-1 block text-sm font-medium text-gray-700">
                                                Übersetzung
                                            </label>
                                            <textarea
                                                data-testid="section-translated-input"
                                                v-model="draftFor(group).translated"
                                                rows="6"
                                                class="block w-full rounded-md border-gray-300 shadow-sm focus:border-amber-500 focus:ring-amber-500"
                                                placeholder="Übersetzter Folientext…"
                                                @input="onSectionInput(group.section_id ?? group.id)"
                                                @blur="onSectionBlur(group.section_id ?? group.id)"
                                            />
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>

                        <!-- Arrangement Configurator -->
                        <div class="px-6 py-5">
                            <h3 class="mb-4 text-sm font-semibold uppercase tracking-wide text-gray-500">
                                Arrangements
                            </h3>

                            <ArrangementConfigurator
                                :song-id="songData.id"
                                :arrangements="arrangements"
                                :available-groups="availableGroups"
                                @arrangements-changed="fetchSong"
                            />
                        </div>
                    </div>
                </div>
            </div>
        </Transition>
    </Teleport>
</template>
