<script setup lang="ts">
import { Search } from 'lucide-vue-next'
import { Button } from '@/components/ui/button'
import { InputWithIcon } from '@/components/ui/input'
import { Outline } from '@/components/ui/outline'
import { SidebarTrigger } from '@/components/ui/sidebar'
import MusicCard from '~/components/internal/musiccard/MusicCard.vue'
import { DnDOperations, useDroppable } from '@vue-dnd-kit/core'
import Draggable from '~/components/action/Draggable.vue'
import { useCurrentPlaylistStore } from '~/stores/use-current-playlist-store'
import { bulkReorder, getGetPlaylistTracksQueryKey } from '~/composeables/api/track-controller/track-controller'
import { useGetPlaylistTracks } from '~/composeables/api/track-controller/track-controller'
import { useMutation, useQueryClient } from '@tanstack/vue-query'

const searchValue = ref('')


const queryClient = useQueryClient();
const currentPlaylistStore = useCurrentPlaylistStore();

const { data: playlistTracks, isLoading, error, refetch } = useGetPlaylistTracks(
    computed(() => currentPlaylistStore.id),
    {
        query: {
            enabled: computed(() => currentPlaylistStore.id !== -1)
        }
    }
)

const { mutate: reorderTracks } = useMutation({
    mutationFn: ({ playlistId, trackIds }: { playlistId: number; trackIds: number[] }) =>
        bulkReorder(playlistId, { trackIds }),
    onMutate: async ({ playlistId, trackIds }) => {
        await queryClient.cancelQueries({ queryKey: getGetPlaylistTracksQueryKey(playlistId) });

        const previousTracks = queryClient.getQueryData(getGetPlaylistTracksQueryKey(playlistId));

        queryClient.setQueryData(getGetPlaylistTracksQueryKey(playlistId), (old: any) => {
            if (!old) return old;
            return {
                ...old,
                data: trackIds.map(id => old.data.find((t: any) => t.trackId === id || t.id === id)),
            };
        });

        return { previousTracks };
    },
    onError: (err, { playlistId }, context) => {
        console.log(err)
        if (context?.previousTracks) {
            queryClient.setQueryData(getGetPlaylistTracksQueryKey(playlistId), context.previousTracks);
        }
    },
    onSettled: () => {
        queryClient.invalidateQueries({ queryKey: getGetPlaylistTracksQueryKey(currentPlaylistStore.id) });
    },
});


const trackCount = computed(() => playlistTracks.value?.data.length || 0)

const mappedTracks = computed(() => {
    if (!playlistTracks.value) return []
    const tracks = playlistTracks.value.data

    return tracks.map((track: any, index: number) => ({
        id: track.trackId || track.id,
        title: track.track?.title || track.title || 'Unknown Track',
        author: track.track?.artist?.name || track.artist || 'Unknown Artist',
        authorLabel: "Artist",
        badges: track.track?.format ? [track.track.format] : ['mp3'],
        imageUrl: track.track?.coverUrl || track.coverUrl || getDefaultImage(index),
        date: formatDate(track.addedDate || track.createdAt),
        selected: false
    }))
})

const getDefaultImage = (index: number) => {
    const defaultImages = [
        "https://github.com/yavuzceliker/sample-images/blob/main/docs/image-1.jpg?raw=true",
        "https://github.com/yavuzceliker/sample-images/blob/main/docs/image-2.jpg?raw=true",
        "https://github.com/yavuzceliker/sample-images/blob/main/docs/image-3.jpg?raw=true",
        "https://github.com/yavuzceliker/sample-images/blob/main/docs/image-5.jpg?raw=true"
    ]
    return defaultImages[index % defaultImages.length]
}

const formatDate = (dateString: string) => {
    if (!dateString) return 'recently added'

    const date = new Date(dateString)
    const now = new Date()
    const diffTime = Math.abs(now.getTime() - date.getTime())
    const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24))

    if (diffDays === 1) return 'yesterday'
    if (diffDays < 7) return `${diffDays} days ago`
    if (diffDays < 30) return `${Math.floor(diffDays / 7)} weeks ago`
    if (diffDays < 365) return `${Math.floor(diffDays / 30)} months ago`
    return `${Math.floor(diffDays / 365)} years ago`
}

const filteredTracks = computed(() => {
    if (!searchValue.value) return mappedTracks.value

    return mappedTracks.value.filter(track =>
        track.title.toLowerCase().includes(searchValue.value.toLowerCase()) ||
        track.author.toLowerCase().includes(searchValue.value.toLowerCase()) ||
        track.badges.some(badge => badge.toLowerCase().includes(searchValue.value.toLowerCase()))
    )
})

const selectTrack = (trackId: number) => {
    mappedTracks.value.forEach(track => {
        track.selected = track.id === trackId
    })
}

const { elementRef: tracksRef } = useDroppable({
    data: {
        source: mappedTracks.value,
    },
    events: {
        onDrop: (store, payload) => {
            DnDOperations.applyTransfer(store);
            if (currentPlaylistStore.id === -1) return;
            if (mappedTracks.value.length !== trackCount.value) return;
            if (mappedTracks.value.some(t => !t)) return;

            const trackIds = mappedTracks.value?.map(t => t.id);
            reorderTracks({
                playlistId: currentPlaylistStore.id,
                trackIds,
            });
        },
    },
});

watch(() => currentPlaylistStore.id, (newId) => {
    if (newId !== -1) {
        refetch()
    }
})
</script>

<template>
    <div class="flex-1">
        <NuxtLayout name="default">
            <template #header>
                <Outline side="bottom" padding="dense" class="w-full flex">
                    <div class="flex gap-8 w-full items-center">
                        <SidebarTrigger :size="5" />
                        <h2 class="scroll-m-20 text-3xl font-semibold tracking-tight transition-colors first:mt-0">
                            Tracks
                        </h2>
                    </div>
                    <Button>
                        Export
                    </Button>
                </Outline>
            </template>
            <div class="flex flex-col w-full p-4 gap-4 h-full">
                <InputWithIcon v-model="searchValue" :icon="Search" placeholder="Search..." type="search" icon-size="5"
                    id="user-search" class="w-full" />

                <div ref="tracksRef">
                    <div v-if="isLoading" class="flex justify-center items-center py-8">
                        <p>Loading tracks...</p>
                    </div>

                    <div v-else-if="error" class="flex justify-center items-center py-8">
                        <p class="text-red-500">Error loading tracks: {{ error }}</p>
                    </div>

                    <div v-else-if="!filteredTracks.length" class="flex justify-center items-center py-8">
                        <p v-if="searchValue">No tracks found matching "{{ searchValue }}"</p>
                        <p v-else>No tracks in this playlist</p>
                    </div>

                    <div v-else ref="tracksRef" class="space-y-2">
                        <TransitionGroup name="list" ref="tracksRef">
                            <Draggable v-for="(track, index) in filteredTracks" :key="track.id" :index="index"
                                :source="mappedTracks">
                                <MusicCard :key="track.id" :title="track.title" :author="track.author"
                                    :authorLabel="track.authorLabel" :badges="track.badges" :imageUrl="track.imageUrl"
                                    :date="track.date" :selected="track.selected" @click="selectTrack(track.id)" />
                            </Draggable>
                        </TransitionGroup>
                    </div>
                </div>
            </div>
            <template #sidebar>
                <Outline padding="none" class="h-full" side="left">
                    <Outline padding="dense" side="bottom">
                        <p class="leading-7 not-first:mt-6 font-semibold">
                            Metadata editor
                        </p>
                    </Outline>
                </Outline>
            </template>
        </NuxtLayout>
    </div>
</template>

<style>
.list-move {
    transition: 0.3s cubic-bezier(0.165, 0.84, 0.44, 1);
}

.list-enter-active,
.list-leave-active {
    transition: 0.3s cubic-bezier(0.165, 0.84, 0.44, 1);
}

.list-enter-from,
.list-leave-to {
    opacity: 0;
    transform: translateY(-20px);
}

.list-leave-active {
    position: absolute;
    pointer-events: none;
}
</style>
