<script lang="ts">
  import { type BuzzerFile, SyncState } from "../lib/types";
  import {
    MusicNotesIcon,
    DotsThreeVerticalIcon,
    PlayIcon,
    TrashIcon,
    PencilIcon,
    CircleIcon,
    QuestionIcon,
    TagIcon,
    UserIcon,
    CheckCircleIcon,
    WarningIcon,
    WarningCircleIcon,
    CloudArrowDownIcon,
  } from "phosphor-svelte";
  import {
    isTransferingRemote,
    transferStats,
    transferDetails,
    buzzerAudioFiles,
    localAudioFiles,
    syncStateMap,
    fsInfo,
  } from "../lib/store";

  import { SETTINGS } from "../lib/settings";
  import { tagEditorState } from "../lib/store";
  import { tooltip } from "../lib/actions/tooltip";
  import { deleteRemoteFile } from "../lib/transport";
  import { deleteLocalFile, playLocalFile, downloadLocalFile } from "../lib/db";
  import { refreshRemote, refreshLocal } from "../lib/sync";
  import { addToast } from "../lib/toast";

  export let file: BuzzerFile;
  export let type: "local" | "buzzer" = "buzzer";
  let menuOpen = false;

  $: activeStore = type === "local" ? localAudioFiles : buzzerAudioFiles;
  $: selectedFiles = $activeStore.filter((f) => f.selected);
  $: currentIndex = selectedFiles.findIndex((f) => f.name === $transferStats.currentFileName);
  $: myIndex = selectedFiles.findIndex((f) => f.name === file.name);

  $: state = (() => {
    if (!file.selected || !$isTransferingRemote) return "default";
    if (file.name === $transferStats.currentFileName) return "active";
    if (myIndex < currentIndex) return "done";
    if (myIndex > currentIndex) return "pending";
    return "default";
  })();

  $: syncStatus = $syncStateMap[type][file.name] || { state: SyncState.UNKNOWN, linkedFiles: [] };

  $: statusConfig = (() => {
    switch (syncStatus.state) {
      case SyncState.UNKNOWN:
        return {
          icon: QuestionIcon,
          weight: "fill",
          color: "text-amber-500",
          variant: "warning",
          text: "Prüfsumme fehlt. Bitte Metadaten aktualisieren.",
        };
      case SyncState.SINGLE_SIDED:
        return {
          icon: CircleIcon,
          weight: "bold",
          color: "text-emerald-600",
          variant: "info",
          text: `Datei existiert nur ${type === "buzzer" ? "auf dem Buzzer" : "lokal"}.`,
        };
      case SyncState.SYNCED:
        return {
          icon: CheckCircleIcon,
          weight: "fill",
          color: "text-emerald-500",
          variant: "info",
          text: "Datei ist synchronisiert.",
        };
      case SyncState.CONFLICT:
        return {
          icon: WarningIcon,
          ping: true,
          weight: "fill",
          color: "text-amber-600",
          variant: "warning",
          text: `Konflikt: Name/Tags weichen ab. Vergleiche mit <span class="text-medium text-on-surface bg-white rounded px-1">${syncStatus.linkedFiles[0]}</span>  ${type === "buzzer" ? "lokal" : "auf dem Buzzer"}`,
        };
      case SyncState.DUPLICATE:
        const duplicateText =
          syncStatus.linkedFiles.length === 0
            ? `Diese Datei ist hier ok, aber ${type === "buzzer" ? "lokal" : "auf dem Buzzer"} existieren mehrere identische Versionen.`
            : `Mehrfach vorhanden: Gleicher Inhalt auch in <span class="text-medium text-on-surface bg-white rounded px-1">${syncStatus.linkedFiles.join("</span>  <span class='text-medium text-on-surface bg-white rounded px-1'>")}</span>`;
        return {
          icon: WarningCircleIcon,
          ping: true,
          weight: "fill",
          color: "text-red-600",
          variant: "danger",
          text: duplicateText,
        };
      default:
        return null;
    }
  })();

  function toggleSelection() {
    if ($isTransferingRemote) return;

    if (type === "buzzer") {
      buzzerAudioFiles.update((files) =>
        files.map((entry) =>
          entry.name === file.name ? { ...entry, selected: !entry.selected } : entry,
        ),
      );
      return;
    }

    localAudioFiles.update((files) =>
      files.map((entry) =>
        entry.name === file.name ? { ...entry, selected: !entry.selected } : entry,
      ),
    );
  }

  async function handleDeleteClick() {
    if (!confirm(`Möchten Sie die Datei "${file.name}" wirklich löschen?`)) {
      menuOpen = false;
      return;
    }

    if (type === "buzzer") {
      try {
        const basePath = $fsInfo?.audioPath || "/lfs/a";
        const fullPath = `${basePath}/${file.name}`;
        await deleteRemoteFile(fullPath);
        addToast(`Datei ${file.name} erfolgreich vom Buzzer gelöscht.`, "success");
        await refreshRemote();
      } catch (error) {
        console.error("Fehler beim Löschen:", error);
        addToast("Fehler beim Löschen der Datei auf dem Buzzer.", "error");
      }
    } else {
      try {
        await deleteLocalFile(file.name);
        addToast(`Lokale Datei ${file.name} gelöscht.`, "success");
        await refreshLocal();
      } catch (error) {
        console.error("Fehler beim Löschen:", error);
      }
    }
    menuOpen = false;
  }
</script>

<svelte:window on:click={() => (menuOpen = false)} />

<div class="relative overflow-hidden group/item">
  {#if state === "active"}
    <div
      class="absolute top-0 left-0 h-full bg-indigo-100 z-0"
      style="width: {$transferDetails.filePercent}%; transition: {$transferDetails.filePercent === 0
        ? 'none'
        : `width ${SETTINGS.ui.transferUpdateIntervalMs}ms linear`};"
    ></div>
  {/if}

  <!-- svelte-ignore a11y_mouse_events_have_key_events -->
  <button
    class="relative z-10 w-full text-left flex-1 px-3 py-1 pr-16 flex items-center border-l-4 transition-colors border-b border-b-border-card
         {file.selected ? 'border-l-blue-600' : 'border-l-transparent'}
         {file.selected && state !== 'active' ? 'bg-blue-50' : ''}
         {!$isTransferingRemote && file.selected ? 'hover:bg-blue-100 cursor-pointer' : ''}
         {!$isTransferingRemote && !file.selected
      ? 'hover:bg-slate-100 hover:border-l-blue-200 cursor-pointer'
      : ''}
         {$isTransferingRemote ? 'cursor-default' : ''}
         {state === 'pending' ? 'grayscale opacity-80' : ''}"
    on:click={toggleSelection}
    on:mouseenter|stopPropagation={() => (menuOpen = true)}
    on:mouseleave|stopPropagation={() => (menuOpen = false)}
    on:blur|stopPropagation={() => (menuOpen = false)}
    on:focus|stopPropagation={() => (menuOpen = true)}
    disabled={$isTransferingRemote}
  >
    <MusicNotesIcon weight="fill" class="mr-2 w-5 h-5 shrink-0" />

    <div class="flex flex-col flex-1 min-w-0 overflow-hidden pl-1">
      <div class="flex items-center min-w-0">
        <span class="font-light truncate min-w-0 text-sm">
          {file.name || "Unbekannte Datei"}
          {#if file.metaTags?.t}
            &thinsp;-&thinsp;
            <span class="font-normal">{file.metaTags.t}</span>
          {/if}
        </span>
      </div>

      <div class="flex items-center gap-0 text-xs text-text-muted mt-0.5 min-w-0">
        {#if statusConfig}
          <span
            use:tooltip={{
              text: statusConfig.text,
              pos: "right",
              variant: statusConfig.variant,
            }}
          >
            {#if statusConfig.ping}
              <span class="mr-1 relative inline-flex size-3.5">
                <svelte:component
                  this={statusConfig.icon}
                  weight={statusConfig.weight ? statusConfig.weight : "fill"}
                  class="opacity-57 text-amber-600 absolute inline-flex h-full w-full animate-ping"
                />
                <svelte:component
                  this={statusConfig.icon}
                  weight={statusConfig.weight ? statusConfig.weight : "fill"}
                  class="shrink-0 w-3.5 h-3.5 {statusConfig.color}"
                />
              </span>
            {:else}
              <svelte:component
                this={statusConfig.icon}
                weight={statusConfig.weight ? statusConfig.weight : "fill"}
                class="mr-1 shrink-0 w-3.5 h-3.5 {statusConfig.color}"
              />
            {/if}
          </span>
        {/if}

        <span class="font-light shrink-0">
          {parseFloat((file.size / 1024).toFixed(1))}&thinsp;kB
        </span>
        {#if file.metaTags?.a}
          <UserIcon
            weight="fill"
            class="ml-1 pl-1 mr-0.5 shrink-0 text-slate-500 w-4.5 h-3.5 border-l border-l-text-muted"
          />
          <span class="truncate min-w-0">{file.metaTags.a}</span>
        {/if}
        {#if file.metaTags?.c}
          <TagIcon
            weight="fill"
            class="ml-1 pl-1 mr-0.5 shrink-0 text-slate-500 w-4.5 h-3.5 border-l border-l-text-muted"
          />
          <span class="truncate min-w-0">{file.metaTags.c}</span>
        {/if}
      </div>
    </div>
  </button>

  <!-- svelte-ignore a11y_no_static_element_interactions -->
  <!-- svelte-ignore a11y_mouse_events_have_key_events -->
  <div
    class="menu-btn-grp group/menu"
    class:is-open={menuOpen}
    on:mouseout|stopPropagation={() => (menuOpen = false)}
  >
    <div
      class="flex items-center overflow-hidden transition-all duration-300 ease-in-out
             {menuOpen
        ? 'max-w-[120px] opacity-100'
        : 'max-w-0 opacity-0 group-hover/menu:max-w-[120px] group-hover/menu:opacity-100'}"
    >
      <button class="menu-btn danger" title="Löschen" on:click|stopPropagation={handleDeleteClick}>
        <TrashIcon class="list-menu-icon" />
      </button>
      <button
        class="menu-btn"
        title="Abspielen"
        on:click|stopPropagation={() => {
            downloadLocalFile(file.name);
            menuOpen = false;
        }}
      >
        <CloudArrowDownIcon class="list-menu-icon" />
      </button>
      <button
        class="menu-btn"
        title="Abspielen"
        on:click|stopPropagation={() => {
          if (type === "buzzer") {
            addToast;
          } else {
            playLocalFile(file.name);
            menuOpen = false;
          }
        }}
      >
        <PlayIcon class="list-menu-icon" />
      </button>
      <button
        class="menu-btn"
        title="Datei-Info"
        on:click|stopPropagation={() => {
          tagEditorState.set({ show: true, type, fileName: file.name });
          menuOpen = false;
        }}
      >
        <PencilIcon class="list-menu-icon" />
      </button>
    </div>

    <button
      class="menu-btn !border-r-transparent"
      on:click|stopPropagation={() => (menuOpen = !menuOpen)}
    >
      <DotsThreeVerticalIcon class="list-menu-icon" />
    </button>
  </div>
</div>

<style>
  @reference "../styles/app.css";

  .menu-btn-grp {
    @apply absolute right-2 top-1/2 -translate-y-1/2 z-20 overflow-hidden
      p-0 flex items-center backdrop-blur-sm 
      rounded-full transition-all;
  }

  /* Kombiniert Hover von Mausnutzern und aktiven Touch-Zustand */
  .menu-btn-grp:hover,
  .menu-btn-grp.is-open {
    @apply bg-white shadow-sm;
  }

  .menu-btn {
    @apply border-r border-r-border-card
    flex items-center justify-center shrink-0 transition-colors;

    &:not(:disabled):not(.danger) {
      @apply hover:bg-surface-hover;
    }

    &.danger:not(:disabled) {
      @apply text-red-700 hover:bg-red-100;
    }

    &:disabled {
      color: color-mix(in srgb, currentColor 50%, transparent);
      @apply cursor-not-allowed grayscale;
    }
  }
</style>
