"use client";

import { useMutation, useQueryClient } from "@tanstack/react-query";
import { toast } from "sonner";
import { useCan } from "@/features/auth/use-can";
import { useT } from "@/i18n";
import { cn } from "@/lib/cn";
import { friendlyErrorMessage } from "@/lib/errors";
import { queryKeys } from "@/lib/query-keys";
import { mergeOrderCollection, splitOrderCollection } from "@/services/orders";
import type { Order } from "@/types/order";

/**
 * Who collects from the suppliers: one captain for all of them, or one captain each.
 *
 * The office chooses, and can change its mind until somebody starts. The choice decides which assign buttons exist: **one captain** is a
 * single Assign for the whole errand; **a captain per supplier** is an Assign on each supplier. The server says what is still possible
 * (`can_merge_collection` to go back to one captain, `can_split_collection` to go to one each), and once a captain holds a supplier or
 * something is collected neither is, so the choice is shown but locked.
 *
 * Shown for any order with several suppliers; nothing for an order with one.
 */
export function CollectionMode({ order }: { order: Order }) {
  const t = useT();
  const { can } = useCan();
  const queryClient = useQueryClient();

  const legs = (order.collection_legs ?? []).filter((leg) => leg.resolved_at == null);
  const split = order.leg === "delivery" && legs.length > 0;

  // How many suppliers the order is collected from, wherever they are written down.
  const suppliers = split ? legs.reduce((sum, leg) => sum + Math.max(1, (leg.stops ?? []).length), 0) : (order.pickups ?? []).length;

  // One each means several collections, one per supplier; everything else is one captain for all of them.
  const perSupplier = split && legs.length > 1;

  const change = useMutation({
    mutationFn: () => (perSupplier ? mergeOrderCollection(order.uuid) : splitOrderCollection(order.uuid)),
    onSuccess: (response) => {
      toast.success(response.Message ?? t("orders.mode.done"));
      void queryClient.invalidateQueries({ queryKey: queryKeys.orders.detail(order.uuid) });
      void queryClient.invalidateQueries({ queryKey: ["orders"] });
    },
    onError: (error) => toast.error(friendlyErrorMessage(error, t)),
  });

  if (suppliers < 2 || !can("orders.assign") || order.leg === "collection") {
    return null;
  }

  const canGoSingle = perSupplier && order.can_merge_collection === true;
  const canGoPerSupplier = !perSupplier && order.can_split_collection === true;
  const hubMissing = !perSupplier && order.split_blocked === "hub_not_configured";
  const locked = !canGoSingle && !canGoPerSupplier && !hubMissing;

  const options = [
    { key: "single", active: !perSupplier, enabled: canGoSingle, title: t("orders.mode.single"), hint: t("orders.mode.singleHint") },
    { key: "perSupplier", active: perSupplier, enabled: canGoPerSupplier, title: t("orders.mode.perSupplier"), hint: t("orders.mode.perSupplierHint") },
  ] as const;

  return (
    <div>
      <p className="mb-3 text-sm font-medium text-foreground">{t("orders.mode.title")}</p>

      <div role="radiogroup" aria-label={t("orders.mode.title")} className="grid gap-2 sm:grid-cols-2">
        {options.map((option) => (
          <button
            key={option.key}
            type="button"
            role="radio"
            aria-checked={option.active}
            disabled={option.active || !option.enabled || change.isPending}
            onClick={() => change.mutate()}
            className={cn(
              "rounded-lg border p-4 text-start transition-colors",
              option.active ? "border-primary bg-primary-soft/40" : "hover:bg-muted/40",
              !option.active && !option.enabled && "cursor-not-allowed opacity-60",
            )}
          >
            <span className="block text-sm font-semibold text-foreground">{option.title}</span>
            <span className="mt-0.5 block text-xs text-muted-foreground">{option.hint}</span>
          </button>
        ))}
      </div>

      {change.isPending ? (
        <p className="mt-2 inline-flex items-center gap-2 text-xs text-muted-foreground" role="status">
          <span aria-hidden className="h-3.5 w-3.5 animate-spin rounded-full border-2 border-current border-t-transparent" />
          {t("common.saving")}
        </p>
      ) : null}
      {order.leg === "delivery" && !perSupplier ? <p className="mt-2 text-xs text-muted-foreground">{t("orders.mode.wrappedNote")}</p> : null}
      {hubMissing ? <p className="mt-2 text-xs text-warning">{t("orders.split.hubMissing")}</p> : null}
      {locked ? <p className="mt-2 text-xs text-muted-foreground">{t("orders.mode.locked")}</p> : null}
    </div>
  );
}
