<script lang="ts" module>
  export type DiscoverCardKind = 'artist' | 'album' | 'track';
  // 'snoozed' is a transient state the card flips to in place after the user
  // parks it, so the disappearance is legible and undoable rather than a card
  // silently vanishing from under the cursor (rule #24). The row is gone on
  // the next refetch; the persistent way back is the snoozed list.
  export type DiscoverCardState = 'requestable' | 'kept' | 'requested' | 'snoozed';
</script>

<script lang="ts">
  import { Plus, Disc3, Album, Music2, Clock } from 'lucide-svelte';

  let {
    kind,
    title,
    subtitle,
    imageUrl,
    state,
    attribution,
    onRequest,
    onSnooze,
    onUnsnooze,
  }: {
    kind: DiscoverCardKind;
    title: string;
    subtitle?: string;
    imageUrl?: string;
    state: DiscoverCardState;
    attribution?: string;
    onRequest?: () => void;
    // Omit both to get a card with no snooze affordance — the Lidarr search
    // results reuse this component and have nothing to park.
    onSnooze?: () => void;
    onUnsnooze?: () => void;
  } = $props();

  const FallbackIcon = $derived(
    kind === 'artist' ? Disc3 : kind === 'album' ? Album : Music2
  );

  function handleRequest() {
    if (state === 'requestable') onRequest?.();
  }
</script>

<article
  class="card rounded-lg border border-border bg-surface p-3"
  data-state={state}
>
  <div
    class="art flex aspect-square w-full items-center justify-center overflow-hidden rounded-md bg-surface-hover"
  >
    {#if imageUrl}
      <img
        src={imageUrl}
        alt=""
        loading="lazy"
        class="h-full w-full object-cover"
      />
    {:else}
      <FallbackIcon size={32} strokeWidth={1} class="text-text-muted" />
    {/if}
  </div>

  <div class="text mt-3">
    <div class="title text-base font-medium text-text-primary">{title}</div>
    {#if subtitle}
      <div class="subtitle text-sm text-text-secondary">{subtitle}</div>
    {/if}
    {#if attribution}
      <div class="attribution text-xs italic text-text-secondary" data-testid="attribution">
        {attribution}
      </div>
    {/if}
    <div class="badge-row" data-testid="badge-row">
      {#if state === 'kept'}
        <span class="kept-pill" role="status">Kept</span>
      {:else if state === 'snoozed'}
        <span class="snoozed-pill" role="status">Not right now</span>
      {/if}
    </div>
  </div>

  <div class="actions pt-3" data-testid="actions">
    {#if state === 'snoozed'}
      <button
        type="button"
        aria-label={`Bring ${title} back`}
        class="rounded-md border border-border px-3 py-1.5 text-sm text-text-primary hover:bg-surface-hover focus:outline-none focus:ring-2 focus:ring-accent"
        onclick={() => onUnsnooze?.()}
      >
        Undo
      </button>
    {:else if state === 'requestable'}
      <div class="flex items-center gap-2">
        <button
          type="button"
          aria-label={`Request ${title}`}
          class="flex items-center gap-1 rounded-md bg-action-primary px-3 py-1.5 text-sm text-action-fg"
          onclick={handleRequest}
        >
          <Plus size={16} strokeWidth={1} /> Request
        </button>
        {#if onSnooze}
          <!--
            Icon-only to keep Request unambiguously the primary action, with
            the intent carried by the accessible name. "Not right now" is the
            whole point of the wording: this parks a suggestion, it does not
            record an opinion about the artist (rule #101).
          -->
          <button
            type="button"
            aria-label={`Not right now — hide ${title} for a while`}
            title="Not right now"
            class="rounded-md border border-border p-1.5 text-text-secondary hover:bg-surface-hover hover:text-text-primary focus:outline-none focus:ring-2 focus:ring-accent"
            onclick={() => onSnooze?.()}
          >
            <Clock size={16} strokeWidth={1} />
          </button>
        {/if}
      </div>
    {:else if state === 'kept'}
      <button
        type="button"
        disabled
        aria-label={`${title} is already in library`}
        onclick={handleRequest}
        class="rounded-md border border-border px-3 py-1.5 text-sm text-text-muted"
      >
        In library
      </button>
    {:else}
      <button
        type="button"
        disabled
        aria-label={`${title} already requested`}
        onclick={handleRequest}
        class="rounded-md border border-border px-3 py-1.5 text-sm text-text-muted"
      >
        Requested
      </button>
    {/if}
  </div>
</article>

<style>
  .card {
    display: flex;
    flex-direction: column;
  }
  .text {
    display: flex;
    flex-direction: column;
    gap: 4px;
  }
  .badge-row {
    min-height: 22px;
    display: flex;
    align-items: center;
  }
  .actions {
    margin-top: auto;
  }
  .kept-pill {
    display: inline-flex;
    align-items: center;
    padding: 2px 8px;
    border-radius: 999px;
    font-size: 11px;
    line-height: 14px;
    background: color-mix(in srgb, var(--fs-accent) 15%, transparent);
    color: var(--fs-accent);
  }
  /* Muted rather than accented: a parked card should recede, not compete
     with the live suggestions around it. Same geometry as .kept-pill so the
     two read as one component in different states. */
  .snoozed-pill {
    display: inline-flex;
    align-items: center;
    padding: 2px 8px;
    border-radius: 999px;
    font-size: 11px;
    line-height: 14px;
    background: var(--fs-slate);
    color: var(--fs-vellum);
  }
  .card[data-state='snoozed'] {
    opacity: 0.6;
  }
</style>
