import type { JellyItem } from './shared';
import { Link, useLocation, useSearchParams } from 'react-router';
import { Check, Play } from 'lucide-react';
import { useClient } from 'hooks/useClient';
import { episodeLabel, itemHref, posterUrl, progressPercent, subtitleFor, thumbUrl } from './shared';

// One tile in a shelf or a grid.
//
// It is a real <Link> to `?item=<id>` — cmd-click opens the detail in a new tab, the URL says what is open,
// and the back button closes it. The play button is a SIBLING anchor rather than nested inside, because an
// anchor inside an anchor is not valid HTML and browsers resolve it by dropping one of them.

type MediaCardProps = { item: JellyItem; wide?: boolean };

export const MediaCard = ({ item, wide = false }: MediaCardProps) => {
  const { token } = useClient();
  const { pathname } = useLocation();
  const [params] = useSearchParams();

  const src = wide ? thumbUrl(item, token) : posterUrl(item, token);
  const progress = progressPercent(item);
  const watched = item.UserData?.Played === true;
  const unplayed = item.UserData?.UnplayedItemCount ?? 0;
  const subtitle = subtitleFor(item);

  return (
    <div className="group/card flex flex-col gap-1.5">
      <div className="relative">
        <Link
          to={itemHref(pathname, params, item.Id)}
          className={`relative block overflow-hidden rounded-lg bg-muted ring-1 ring-black/5 transition-transform hover:scale-[1.02] ${
            wide ? 'aspect-video' : 'aspect-[2/3]'
          }`}
          title={item.Name ?? undefined}
        >
          {src ? (
            <img src={src} alt="" loading="lazy" className="h-full w-full object-cover" />
          ) : (
            <div className="flex h-full w-full items-center justify-center p-2 text-center text-[11px] text-muted-foreground">
              {item.Name}
            </div>
          )}

          {watched && (
            <span className="absolute right-1.5 top-1.5 flex h-5 w-5 items-center justify-center rounded-full bg-primary text-primary-foreground">
              <Check className="h-3 w-3" />
            </span>
          )}
          {!watched && unplayed > 0 && (
            <span className="absolute right-1.5 top-1.5 rounded-full bg-primary px-1.5 py-0.5 text-[10px] font-medium text-primary-foreground">
              {unplayed}
            </span>
          )}

          {progress > 0 && progress < 100 && (
            <span className="absolute inset-x-0 bottom-0 h-1 bg-black/40">
              <span className="block h-full bg-primary" style={{ width: `${progress}%` }} />
            </span>
          )}
        </Link>

        <Link
          to={itemHref(pathname, params, item.Id, true)}
          aria-label={`Play ${item.Name ?? 'item'}`}
          className="absolute left-1/2 top-1/2 flex h-11 w-11 -translate-x-1/2 -translate-y-1/2 items-center justify-center rounded-full bg-black/70 text-white opacity-0 transition-opacity group-hover/card:opacity-100"
        >
          <Play className="h-5 w-5 translate-x-px" fill="currentColor" />
        </Link>
      </div>

      <div className="min-w-0">
        <p className="truncate text-xs font-medium leading-tight">{episodeLabel(item)}</p>
        {subtitle && <p className="truncate text-[11px] text-muted-foreground">{subtitle}</p>}
      </div>
    </div>
  );
};

/** A horizontal shelf. Overflow scrolls rather than wrapping — a shelf that wraps is a grid with a title. */
export const MediaShelf = ({ title, items, wide }: { title: string; items: JellyItem[]; wide?: boolean }) => {
  if (!items.length) return null;
  return (
    <section className="flex flex-col gap-2">
      <h3 className="px-1 text-sm font-semibold">{title}</h3>
      <div className="flex gap-3 overflow-x-auto pb-2">
        {items.map((item) => (
          <div key={item.Id} className={wide ? 'w-56 shrink-0' : 'w-32 shrink-0'}>
            <MediaCard item={item} wide={wide} />
          </div>
        ))}
      </div>
    </section>
  );
};

/** A wrapping grid. Column count comes from a min tile width, so it works in a panel of any size. */
export const MediaGrid = ({ items, wide }: { items: JellyItem[]; wide?: boolean }) => (
  <div
    className="grid gap-x-3 gap-y-4"
    style={{ gridTemplateColumns: `repeat(auto-fill, minmax(${wide ? 200 : 130}px, 1fr))` }}
  >
    {items.map((item) => (
      <MediaCard key={item.Id} item={item} wide={wide} />
    ))}
  </div>
);
