<script lang="ts">
  import {
    MoreVertical,
    ListVideo,
    ListMusic,
    Heart,
    HeartOff,
    ListPlus,
    Radio,
    Disc3,
    User,
    EyeOff,
    Eye
  } from 'lucide-svelte';
  import { goto } from '$app/navigation';
  import { useQueryClient } from '@tanstack/svelte-query';
  import FlagPopover from './FlagPopover.svelte';
  import AddToPlaylistMenu from './AddToPlaylistMenu.svelte';
  import TrackMenuItem from './TrackMenuItem.svelte';
  import TrackMenuDivider from './TrackMenuDivider.svelte';
  import { createLikedIdsQuery, likeEntity, unlikeEntity } from '$lib/api/likes';
  import { createMyQuarantineQuery, unflagTrack } from '$lib/api/quarantine';
  import { qk } from '$lib/api/queries';
  import { playNext, enqueueTrack, playRadio } from '$lib/player/store.svelte';
  import type { TrackRef } from '$lib/api/types';

  let {
    track,
    direction = 'down',
    hideQueueActions = false
  }: {
    track: TrackRef;
    /** Whether the dropdown opens above the trigger ('up') or below ('down').
        Pass 'up' when used near the bottom of the viewport (e.g. PlayerBar). */
    direction?: 'up' | 'down';
    /** Hide "Play next" / "Add to queue". Set true on the PlayerBar where
        the menu's track IS the currently-playing one — those actions have
        no meaningful semantics for the track you're already listening to. */
    hideQueueActions?: boolean;
  } = $props();

  let menuOpen = $state(false);
  let flagOpen = $state(false);
  let addOpen = $state(false);

  const queryClient = useQueryClient();

  const likedQ = $derived(createLikedIdsQuery());
  const liked = $derived.by(() => {
    const data = $likedQ?.data;
    if (!data) return false;
    return data.track_ids.includes(track.id);
  });

  const hiddenQ = $derived(createMyQuarantineQuery());
  const hidden = $derived.by(() => {
    const rows = $hiddenQ?.data;
    if (!rows) return false;
    return rows.some((r) => r.track_id === track.id);
  });

  function toggleMenu(e: MouseEvent) {
    e.stopPropagation();
    menuOpen = !menuOpen;
  }

  function closeAll() {
    menuOpen = false;
    flagOpen = false;
    addOpen = false;
  }

  function onPlayNext() {
    playNext(track);
    closeAll();
  }

  function onAddToQueue() {
    enqueueTrack(track);
    closeAll();
  }

  function onStartRadio() {
    playRadio(track.id);
    closeAll();
  }

  async function onToggleLike() {
    closeAll();
    if (liked) {
      await unlikeEntity(queryClient, 'track', track.id);
    } else {
      await likeEntity(queryClient, 'track', track.id);
    }
  }

  async function onToggleHide() {
    if (hidden) {
      // Unhide: simple — unflag, then refresh the quarantine list.
      await unflagTrack(track.id);
      await queryClient.invalidateQueries({ queryKey: qk.myQuarantine() });
      closeAll();
    } else {
      // Hide: needs a reason. Reuse FlagPopover.
      menuOpen = false;
      flagOpen = true;
    }
  }

  function onGoToAlbum() {
    closeAll();
    goto(`/albums/${track.album_id}`);
  }

  function onGoToArtist() {
    closeAll();
    goto(`/artists/${track.artist_id}`);
  }

  function onKeydown(e: KeyboardEvent) {
    if (!menuOpen && !flagOpen && !addOpen) return;
    if (e.key === 'Escape') {
      e.preventDefault();
      closeAll();
    }
  }
</script>

<svelte:window onclick={() => { menuOpen = false; addOpen = false; }} onkeydown={onKeydown} />

<div class="relative inline-block">
  <button
    type="button"
    aria-label={`Track actions for ${track.title}`}
    aria-haspopup="menu"
    aria-expanded={menuOpen}
    onclick={toggleMenu}
    class="rounded p-1 text-text-muted hover:text-text-primary"
  >
    <MoreVertical size={16} strokeWidth={1} />
  </button>

  {#if menuOpen}
    <div
      role="menu"
      tabindex="-1"
      class="absolute right-0 z-20 w-56 rounded-md border border-border bg-surface p-1 shadow-lg
             {direction === 'up' ? 'bottom-full mb-1' : 'top-full mt-1'}"
      onclick={(e) => e.stopPropagation()}
      onkeydown={(e) => { e.stopPropagation(); if (e.key === 'Escape') menuOpen = false; }}
    >
      <!-- Item set + order mirror Android's canonical TrackActionsSheet so
           the kebab reads the same on both clients: queue group → like /
           add-to-playlist / start-radio group → navigation group → hide.
           "Start radio" is shown even under hideQueueActions (reseeding a
           station from the current track is meaningful where play-next /
           add-to-queue are not). No single-click destructive action lives
           here — track removal is intentionally kept out of the kebab. -->
      {#if !hideQueueActions}
        <TrackMenuItem icon={ListVideo} label="Play next" onclick={onPlayNext} />
        <TrackMenuItem icon={ListMusic} label="Add to queue" onclick={onAddToQueue} />

        <TrackMenuDivider />
      {/if}

      <TrackMenuItem
        icon={liked ? HeartOff : Heart}
        label={liked ? 'Unlike' : 'Like'}
        onclick={onToggleLike}
      />
      <TrackMenuItem
        icon={ListPlus}
        label="Add to playlist…"
        onclick={() => { addOpen = true; menuOpen = false; }}
      />
      <TrackMenuItem icon={Radio} label="Start radio" onclick={onStartRadio} />

      <TrackMenuDivider />

      <TrackMenuItem icon={Disc3} label="Go to album" onclick={onGoToAlbum} />
      <TrackMenuItem icon={User} label="Go to artist" onclick={onGoToArtist} />

      <TrackMenuDivider />

      <TrackMenuItem
        icon={hidden ? Eye : EyeOff}
        label={hidden ? 'Unhide' : 'Hide'}
        onclick={onToggleHide}
      />
    </div>
  {/if}

  {#if flagOpen}
    <FlagPopover {track} onClose={closeAll} />
  {/if}

  {#if addOpen}
    <AddToPlaylistMenu tracks={[track]} onClose={() => (addOpen = false)} />
  {/if}
</div>
