"use client";

import { ImageOff } from "lucide-react";
import { useState } from "react";
import { Badge } from "@/components/ui/badge";
import type { OrderItem } from "@/types/order";

/**
 * One line of an order, drawn so it can be told apart from the line below it.
 *
 * A name and a quantity are not enough to pick goods off a counter. Two rows reading
 * "Cotton shirt ×2" are the same row until one of them says "red · L", and the captain only finds
 * out which they took when the customer refuses it at the door. The store sends a picture, a code
 * and a set of attributes for exactly this, and none of them were being shown.
 *
 * The attribute keys belong to the store, not to us — a shop selling cake sends `flavour`, a shop
 * selling shirts sends `size` — so they are rendered as pairs rather than read by name.
 */
export function OrderItemLine({ item }: { item: OrderItem }) {
  const variant = Object.entries(item.variant ?? {});

  return (
    <div className="flex items-start gap-3">
      <ItemThumbnail url={item.image_url} name={item.name} />

      <div className="min-w-0">
        <p className="font-medium text-foreground">{item.name}</p>

        {variant.length > 0 ? (
          <div className="mt-1 flex flex-wrap gap-1">
            {variant.map(([key, value]) => (
              <Badge key={key} variant="secondary" className="font-normal">
                <span className="text-muted-foreground">{key}</span>
                <span className="mx-1 text-muted-foreground">·</span>
                {value}
              </Badge>
            ))}
          </div>
        ) : null}

        {item.sku ? (
          <p className="mt-1 font-mono text-xs text-muted-foreground" dir="ltr">
            {item.sku}
          </p>
        ) : null}

        {item.note ? <p className="mt-1 text-xs text-muted-foreground">{item.note}</p> : null}
      </div>
    </div>
  );
}

/**
 * The store's picture, and something sensible when there is not one.
 *
 * The URL is the store's, not ours: we keep the link rather than the file, so it can rot without
 * anybody here noticing. A broken image would otherwise draw the browser's torn-page icon in the
 * middle of a table, which reads as a fault in this screen rather than a dead link on theirs.
 */
function ItemThumbnail({ url, name }: { url: string | null; name: string }) {
  const [failed, setFailed] = useState(false);

  if (!url || failed) {
    return (
      <span className="flex h-10 w-10 shrink-0 items-center justify-center rounded-md border bg-muted/40 text-muted-foreground">
        <ImageOff className="h-4 w-4" aria-hidden />
      </span>
    );
  }

  return (
    // Not next/image: the host is whatever the store configured, and an unknown remote host is
    // refused by the image optimiser at request time rather than at build time.
    // eslint-disable-next-line @next/next/no-img-element
    <img
      src={url}
      alt={name}
      loading="lazy"
      onError={() => setFailed(true)}
      className="h-10 w-10 shrink-0 rounded-md border object-cover"
    />
  );
}
