<script setup lang="ts">
import Heading from '@/components/Heading.vue'
import { Badge } from '@/components/ui/crm-badge/'
import AppLayout from '@/layouts/AppLayout.vue'
import { daysFromNow, isSoon, isToday, toCurrency, toDuration } from '@/lib/utils'
import { Head } from '@inertiajs/vue3'
import { Calendar, ClipboardCheck, MessageCircle, CircleHelp, Plus, Trash2, Check, SquareCheckBig, MessageSquare } from 'lucide-vue-next'
import { ref, computed } from 'vue'
import axios from 'axios'
import draggable from 'vuedraggable'
import { PipelineLane, PipelineItem, Todo } from '@/types'
import { toast } from 'vue-sonner'
import Button from '@/components/ui/crm-button/Button.vue'
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'
import { DropdownMenuItem } from '@/components/ui/dropdown-menu'
import EditorDialog from '@/components/EditorDialog/EditorDialog.vue'
import TextEditor from '@/components/TextEditor.vue'
import Todos from '@/components/Todos.vue';
import Notes from '@/components/Notes.vue'
import NotesService from '@/services/NotesService'
import TodoService from '@/services/TodoService'
import NumberInput from '@/components/ui/crm-number-input/NumberInput.vue';
import { alertStore } from '@/stores/alertStore'
import PipelineService from '@/services/PipelineService'

interface Props {
    pipeline: PipelineLane[]
}
const props = defineProps<Props>()
const pipeline = ref<PipelineLane[]>(props.pipeline)
const selectedItem = ref<PipelineItem>()
const drag = ref(false)
const dragOptions = ref({
    delay: 100, // only start after 100 ms, so we can click items without dragging
    delayOnTouchOnly: true,

    animation: 200,
    easing: "cubic-bezier(0.33, 1, 0.68, 1)", // out quart
    group: "cards",

    ghostClass: "ghost",  // Class name for the drop placeholder
    chosenClass: "chosen",  // Class name for the chosen item
    dragClass: "drag",  // Class name for the dragging item
})
const editorDialogOpen = ref(false)
const alert = alertStore()

const laneSums = computed(() => {
    const map: Record<number, number> = {}
    pipeline.value.forEach((lane: any) => {
        const sum = (lane.items || []).reduce((acc: number, it: any) => {
            const v = Number(it.expectedRevenue ?? 0)
            return acc + (isNaN(v) ? 0 : v)
        }, 0)
        map[lane.id] = sum
    })
    return map
})

// onMounted(() => {
//     if (pipeline.value[2] && pipeline.value[2].items)
//         editItem(pipeline.value[2].items[1])
// })

const onEndDrag = async function (e: any) {
    drag.value = false

    const changed: Array<{ id: number; pipelineLaneId: number; position: number }> = []

    // Prefer payloads moved/added/removed to decide which lanes to recalc
    const laneIds = new Set<number>()

    const fromLane = getLaneIdFromEl(e.from)
    const toLane = getLaneIdFromEl(e.to)
    if (fromLane !== null) laneIds.add(fromLane)
    if (toLane !== null) laneIds.add(toLane)

    // Recompute positions for affected lanes only
    laneIds.forEach((laneId) => {
        const lane = pipeline.value.find((l: any) => l.id === laneId)
        if (!lane || !Array.isArray(lane.items)) return

        lane.items.forEach((item: any, idx: number) => {
            const newPos = idx
            const newLaneId = laneId
            if (item.position !== newPos || item.pipelineLaneId !== newLaneId) {
                // update in-memory model
                item.position = newPos
                item.pipelineLaneId = newLaneId
                changed.push({ id: item.id, pipelineLaneId: newLaneId, position: newPos })
            }
        })
    })

    if (changed.length === 0) return

    try {
        await persistPositions(changed)
    } catch (e) {
        // on failure, consider reloading or informing the user
        // simple approach: reload canonical data
        toast.error('Could not save positions, reload recommended', { description: (e as Error).message })
    }
}

const persistPositions = async (changed: Array<{ id: number; pipelineLaneId: number; position: number }>) => {
    if (!changed.length) return
    try {
        await axios.post('/api/pipeline/positions', changed)
    } catch (err: Error) {
        toast.error('Failed to persist pipeline positions', { description: err.message })
        throw err
    }
}

const getLaneIdFromEl = (el: any): number | null => {
    try {
        const v = el?.dataset?.laneId
        return v ? Number(v) : null
    } catch (e) {
        return null
    }
}

const cardClasses = (item: PipelineItem): string => {
    // Destructive
    if (item.dueDate && daysFromNow(item.dueDate) < 0 ||
        item.nextTodoDueDate && daysFromNow(item.nextTodoDueDate) < 0
    ) return "border-l-4 border-destructive"

    // Warning
    if (item.dueDate && isSoon(item.dueDate) ||
        item.nextTodoDueDate && isSoon(item.nextTodoDueDate)
    ) return "border-l-4 border-warning"

    return ""
}

const badgeVariant = (date: string | null): "default" | "secondary" | "destructive" | "warning" | "outline" | null | undefined => {
    // Due date
    if (date && daysFromNow(date) < 0) return "destructive"
    else if (date && isSoon(date)) return "warning"
    return "secondary"
}

const itemsNextTodoDueDate = (item: PipelineItem): string | null => {
    if (!item.todos || item.todos.length === 0) return null
    const next = item.todos.find(t => t.status.toLowerCase() !== 'completed')
    return next?.dueDate || null
}

const editItem = async (item: PipelineItem) => {
    // Load todos lazily
    if (item.id !== 0 && (item.todos === undefined || item.todos.length === 0)) {
        TodoService.getTodosForModel('PipelineItem', item.id).then(todos => {
            if (todos) item.todos = todos
        })
    }

    // Load notes lazily
    if (item.id !== 0 && (item.notes === undefined || item.notes.length === 0)) {
        NotesService.getNotesForModel('PipelineItem', item.id).then(notes => {
            if (notes) item.notes = notes
        })
    }

    selectedItem.value = item
    editorDialogOpen.value = true
}

const deleteItem = (item: PipelineItem | undefined) => {
    if (item === undefined) return

    alert.show(
        "Möchtest Du diese Karte wirklich löschen?", null,
        {
            actionText: "Löschen",
            actionVariant: "destructive",
            onAction: async () => {
                PipelineService.deletePipelineItem(item.id).then(deleted => {
                    if (deleted) {
                        let lane = pipeline.value.findIndex(lane => lane.id === item.pipelineLaneId)
                        if (lane === -1) return
                        pipeline.value[lane].items = pipeline.value[lane].items?.filter(i => i.id !== item.id)
                        editorDialogOpen.value = false
                    }
                })
            }
        }
    )
}
const saveItem = (item: PipelineItem | undefined) => {
    if (!item) return
    if (item.id === 0) {
        PipelineService.createPipelineItem(item);
    } else {
        PipelineService.updatePipelineItem(item);
    }
}
</script>


<template>

    <Head title="Vertriebspipeline" />

    <AppLayout title="Vertriebspipeline">

        <div class="flex flex-col h-full">

            <!-- Header -->
            <div class="flex items-start justify-between">
                <div class="flex items-center gap-2">
                    <Heading title="Vertriebspipeline" description="Mache interessante Kontakte zu Kunden"
                        icon="Heading" />
                    <TooltipProvider :delay-duration="0">
                        <Tooltip>
                            <TooltipTrigger as-child>
                                <CircleHelp class="size-4 text-muted-foreground" />
                            </TooltipTrigger>
                            <TooltipContent class="max-w-100">
                                <p>Eine Vetriebspipeline ist ein visuelles und strukturelles System, das den Fortschritt
                                    potenzieller Kunden – von der ersten Kontaktaufnahme (Akquise) bis zum
                                    abgeschlossenen
                                    Verkauf (Projekt) – abbildet. Sie hilft Teams, Chancen zu priorisieren, nächste
                                    Schritte
                                    zu planen und den Vertriebsprozess transparent zu gestalten.</p>

                                <p class="mt-2">Mehr zum Thema <a href="#"
                                        class="text-blue-500 underline hover:text-blue-700">Vertrieb in Caramel</a></p>
                            </TooltipContent>
                        </Tooltip>
                    </TooltipProvider>
                </div>
                <Button>
                    <Plus /> Neue Karte
                </Button>
            </div>


            <!-- Horizontal scroll container -->
            <div class="overflow-x-auto overflow-y-hidden grow flex flex-col max-h-full relative">

                <!-- ------------------------------------------------------- -->
                <!-- Pipeline -->
                <!-- ------------------------------------------------------- -->
                <div
                    class="flex items-center h-16 font-semibold border shadow-md bg-background rounded-lg z-10 absolute min-w-full">

                    <div v-for="(lane, index) in pipeline"
                        class="flex items-center justify-between min-w-64 relative pl-6 pr-6"
                        :style="'width: ' + 100 / pipeline.length + '%'">
                        <div class="flex flex-col grow">
                            <h3 class="text-primary font-semibold">{{ lane.title }}</h3>
                            <span class="text-sm">{{ toCurrency(laneSums[lane.id] || 0) }}</span>
                        </div>
                        <Badge class="rounded-full text-tiny aspect-square p-2.5 h-lh" variant="secondary">
                            {{ lane.items?.length }}</Badge>

                        <svg v-if="index < pipeline.length - 1" viewBox="0 0 19 48" xmlns="http://www.w3.org/2000/svg"
                            class="h-16 absolute -right-2 z-1">
                            <path style="fill:none;stroke:var(--border);stroke-width:1;" d="M 0,0 18,24 0,48" />
                        </svg>
                    </div>
                </div>


                <!-- ------------------------------------------------------- -->
                <!-- Card lanes -->
                <!-- ------------------------------------------------------- -->
                <div class="flex max-h-full">

                    <draggable v-for="(lane, index) in pipeline"
                        class="list-group flex flex-col gap-4 px-4 pt-22 pb-8 overflow-y-auto flex-1 min-w-64 border-x-4 border-main"
                        :class="{ 'bg-sidebar/40': index % 2 > 0 }" :list="lane.items" v-bind="dragOptions"
                        :data-lane-id="lane.id" @start="" @change="" @end="onEndDrag" itemKey="id">

                        <template #item="{ element: item }">

                            <div class="list-group-item bg-background shadow rounded-lg flex flex-col gap-3 p-3 hover:ring-ring hover:ring-[3px] active:bg-accent"
                                :class="cardClasses(item)" @click="editItem(item)" @dblclick="">
                                <h4 class="text font-semibold">{{ item.title }}</h4>
                                <p class="text-sm text-muted-foreground" v-if="item.expectedRevenue > 0">{{
                                    toCurrency(item.expectedRevenue) }}</p>

                                <div class="flex items-center gap-2 flex-wrap">

                                    <Badge v-if="item.dueDate" :variant="badgeVariant(item.dueDate)">
                                        <Calendar />
                                        <span v-if="isToday(item.dueDate)">Heute</span>
                                        <span v-else>{{ toDuration(item.dueDate) }}</span>
                                    </Badge>

                                    <Badge v-if="item.todos && item.todos.length > 0"
                                        :variant="badgeVariant(itemsNextTodoDueDate(item))">
                                        <SquareCheckBig /> {{item.todos.filter(todo => todo.status.toLowerCase() !==
                                            'completed').length}}
                                    </Badge>
                                    <Badge v-else-if="item.todosCount > 0"
                                        :variant="badgeVariant(item.nextTodoDueDate)">
                                        <SquareCheckBig /> {{ item.todosCount }}
                                    </Badge>

                                    <Badge variant="secondary" v-if="item.notes && item.notes.length > 0">
                                        <MessageSquare /> {{ item.notes.length }}
                                    </Badge>
                                    <Badge variant="secondary" v-else-if="item.notesCount > 0">
                                        <MessageSquare /> {{ item.notesCount }}
                                    </Badge>

                                </div>

                            </div>

                        </template>

                    </draggable>

                </div>

            </div>

        </div>


        <!-- --------------------------------------------------------------- -->
        <!-- Editor dialog -->
        <!-- --------------------------------------------------------------- -->
        <EditorDialog :title="selectedItem?.title" v-model="editorDialogOpen">
            <!-- <template v-slot:description>
                Welt
            </template> -->

            <!-- <template v-slot:buttons>
            </template> -->

            <template v-slot:ellipsisMenuItems>
                <DropdownMenuItem
                    class="flex justify-between text-destructive! hover:bg-destructive! hover:text-destructive-foreground!"
                    @click="deleteItem(selectedItem)">
                    <div class="flex items-center gap-3">
                        <Trash2 class="text-current" />
                        <span class="mr-2">Löschen</span>
                    </div>
                </DropdownMenuItem>
            </template>

            <template v-slot:content>
                <TextEditor :model-value="selectedItem?.description"
                    @change:model-value="value => { selectedItem!.description = value; saveItem(selectedItem) }"
                    ref="description-editor" />
                <Notes v-if="selectedItem" title="Protokoll" :notableId="selectedItem.id" notableType="PipelineItem"
                    :modelValue="selectedItem.notes" />
            </template>

            <template v-slot:sidebar>
                <NumberInput label="Erwarteter Umsatz" :modelValue="selectedItem?.expectedRevenue as number" suffix=" €"
                    @update:model-value="console.log" />
                <Todos v-if="selectedItem" :modelValue="selectedItem.todos" :show-completed="false" />
            </template>

        </EditorDialog>

    </AppLayout>
</template>


<style scoped>
.list-group-item {
    cursor: default;
}

.ghost {
    visibility: hidden;
}

.chosen {
    transition: transform 200ms, box-shadow 200ms;
    transition-delay: 200ms;
    box-shadow: var(--shadow-xl);
    transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1);
    transform: rotate(-1deg) scale(1.05);
}
</style>