<script setup lang="ts">
import type { Track, Listening } from '~/types'

import { ref, reactive, watch, computed } from 'vue'
import { useStore } from '~/store'
import { clone } from 'lodash-es'
import { useI18n } from 'vue-i18n'
import { getArtistCoverUrl } from '~/utils/utils'

import axios from 'axios'

import useWebSocketHandler from '~/composables/useWebSocketHandler'
import Button from '~/components/ui/Button.vue'
import PlayButton from '~/components/audio/PlayButton.vue'
import TagsList from '~/components/tags/List.vue'
import Alert from '~/components/ui/Alert.vue'
import Spacer from '~/components/ui/Spacer.vue'
import Loader from '~/components/ui/Loader.vue'

import useErrorHandler from '~/composables/useErrorHandler'


interface Events {
  (e: 'count', count: number): void
}

interface Props {
  filters: Record<string, string | boolean>
  url: string
  isActivity?: boolean
  showCount?: boolean
  limit?: number
  itemClasses?: string
  websocketHandlers?: string[]
}

const emit = defineEmits<Events>()
const props = withDefaults(defineProps<Props>(), {
  isActivity: true,
  showCount: false,
  limit: 5,
  itemClasses: '',
  websocketHandlers: () => []
})

const store = useStore()
const { t } = useI18n()

const objects = reactive([] as Listening[])
const count = ref(0)
const nextPage = ref<string | null>(null)

const isLoading = ref(false)
const fetchData = async (url = props.url) => {
  isLoading.value = true

  const params = {
    ...clone(props.filters),
    page_size: props.limit
  }

  try {
    const response = await axios.get(url, { params })
    nextPage.value = response.data.next
    count.value = response.data.count

    const newObjects = !props.isActivity
      ? response.data.results.map((track: Track) => ({ track }))
      : response.data.results

    objects.push(...newObjects)
  } catch (error) {
    useErrorHandler(error as Error)
  }

  isLoading.value = false
}

watch(
  () => store.state.moderation.lastUpdate,
  () => fetchData(),
  { immediate: true }
)

watch(count, (to) => emit('count', to))

watch(() => props.websocketHandlers.includes('Listen'), (to) => {
  if (to) {
    useWebSocketHandler('Listen', (event) => {
      // Handle WebSocket events for "Listen"

      // Add the event to `objects` reactively
      objects.unshift(event as Listening);

      // Keep the array size within limits (e.g., remove the last item if needed)
      if (objects.length > props.limit) {
        objects.pop();
      }

      // Recompute coverUrl for the updated `objects`
      console.log('WebSocket event received:', event);
      console.log('Updated cover URL:', coverUrl.value);
    });
  }
});

watch(
  objects,
  (newObjects) => {
    // Process each object to attach a `coverUrl`
    newObjects.forEach((object) => {
      const track = object.track;
      if (!("coverUrl" in object)) {
        object.coverUrl = undefined; // Initial value for clarity
      }

      if (track?.album?.cover) {
        object.coverUrl = store.getters["instance/absoluteUrl"](track.album.cover.urls.medium_square_crop);
      } else if (track?.cover) {
        object.coverUrl = store.getters["instance/absoluteUrl"](track.cover.urls.medium_square_crop);
      } else if (track?.artist_credit?.length > 0) {
        object.coverUrl = getArtistCoverUrl(track.artist_credit) || false;
      } else {
        object.coverUrl = false; // Fallback if no cover is found
      }
    });
  },
  { deep: true }
);
</script>

<template>
<!-- TODO: Use activity.vue -->
  <div class="component-track-widget">
    <h3 v-if="!!$slots.title">
      <slot name="title" />
      <span
        v-if="showCount"
        class="ui tiny circular label"
      >{{ count }}</span>
    </h3>
    <Alert
      v-if="count === 0"
      blue
      style="text-align: center;"
    >
      <i class="bi bi-music-note-list" />
      {{ t('components.audio.track.Widget.empty.noResults') }}
      <Loader v-if="isLoading" />
    </Alert>
    <div
      v-if="count > 0"
    >
      <div class="funkwhale activity"
        v-for="object in objects"
        :key="object.id"
        :class="['item', itemClasses]"
        @click="navigate('track')"
      >
        <div class="activity-image">
        <img
            v-if="object.coverUrl"
            v-lazy="object.coverUrl"
            alt="Cover"
          />
          <i
            v-else
            class="bi bi-vinyl-fill"
          />
          <!-- TODO: Add Playbutton overlay -->
        </div>
        <div class="activity-content">
          <div class="track-title">
            <router-link
              class="funkwhale link artist"
              :to="{name: 'library.tracks.detail', params: {id: object.track.id}}"
            >
              {{ object.track.title }}
            </router-link>
          </div>
              <div
                v-if="object.track.artist_credit"
                class="funkwhale link artist"
              >
                <span
                  v-for="ac in object.track.artist_credit"
                  :key="ac.artist.id"
                >
                  <router-link
                    class="discrete link"
                    :to="{ name: 'library.artists.detail', params: { id: ac.artist.id } }"
                  >
                    {{ ac.credit }}
                  </router-link>
                  <span v-if="ac.joinphrase">{{ ac.joinphrase }}</span>
                </span>
              </div>
              <TagsList
                label-classes="tiny"
                :truncate-size="20"
                :limit="2"
                :show-more="false"
                :tags="object.track.tags"
              />

              <div
                v-if="isActivity"
                class="extra"
              >
                <router-link
                  class="funkwhale link user"
                  :to="{name: 'profile.overview', params: {username: object.actor.name}}"
                >
                  <span class="at symbol" />{{ object.actor.name }}
                </router-link>
                <span class="right floated"><human-date :date="object.creation_date" /></span>
              </div>
            </div>
            <play-button
              class="basic icon"
              :account="object.actor"
              :dropdown-only="true"
              :dropdown-icon-classes="['ellipsis', 'vertical', 'large really discrete']"
              :track="object.track"
            />
          </div>
        </div>
      </div>
    <Loader v-if="isLoading" />
    <template v-if="nextPage">
      <Spacer :size="16"/>
      <Button
        primary
        @click="fetchData(nextPage as string)"
      >
        {{ t('components.audio.track.Widget.button.more') }}
      </Button>
    </template>
</template>


<style lang="scss" scoped>
.funkwhale {
  &.activity {
    padding: 12px 0;
    border-top: 1px solid;
    @include light-theme {
      border-color: var(--fw-gray-300);
    }
    @include dark-theme {
      border-color: var(--fw-gray-800);
    }
    cursor: pointer;
    display: grid;
    grid-template-columns: auto 1fr auto;
    gap: 12px;
    grid-column: span 4;

    &:last-child {
      border-bottom: 1px solid;
    }

    > .activity-image {

      width: 40px;
      aspect-ratio: 1;
      overflow: hidden;
      border-radius: var(--fw-border-radius);

      > img {
        width: 100%;
        aspect-ratio: 1;
        object-fit: cover;
      }

      > i {
        font-size: 36px;
      }

      > .play-button {
        position: absolute;
        top: 0;
        left: 0;
        padding: 0 !important;
        width: 100%;
        aspect-ratio: 1;
        margin: 0;
        border: 0 !important;
        opacity: 0;
      }
    }

    &:hover {
      .play-button {
        opacity: 1;
      }
    }

    > .activity-content {

      a {
        text-decoration: none;
        color: var(--color);
      }

      > .track-title {
        font-weight: 700;
        line-height: 1.5em;
        @include dark-theme {
          color: var(--fw-gray-300);
        }
      }

      .artist {
        font-size: 15px;
      }

      .user, time {
        line-height: 1.5em;
        font-size: 0.8125rem;
        color: var(--fw-gray-500);
      }
    }
  }
}

@include light-theme {

  .play-button {
    background: rgba(255, 255, 255, .5);

    &:hover {
      --fw-text-color: var(--fw-gray-800) !important;
    }
  }
}

@include dark-theme {

  .play-button {
    background: rgba(0, 0, 0, .2);

    &:hover {
      background: rgba(0, 0, 0, .8);
      --fw-text-color: var(--fw-gray-200) !important;
    }
  }
}
</style>
