"use client";

import { useState } from "react";
import { useMutation } from "@tanstack/react-query";
import { CheckIcon, ChevronDownIcon, XMarkIcon } from "@heroicons/react/24/outline";
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuLabel,
  DropdownMenuSeparator,
  DropdownMenuTrigger,
} from "@/app/shadcn_components/ui/dropdown-menu";
import { FilterGroups } from "@/app/utils/propertyFilters";
import { tagDotColour } from "@/lib/tags/colour";
import { Tag, useInvalidateTagSurfaces, usePortfolioTags } from "./useTags";

export type TagMode = "assign" | "remove";

/**
 * The contextual strip shown while assigning or removing a tag in bulk
 * (ADR-0013). The target is explicit: the ticked rows, or — after ticking every
 * loaded row — "all N matching", which the user escalates to deliberately and
 * which resolves the whole matching set server-side (not just the loaded page).
 * With nothing selected there is no target, so a tag can't be applied by
 * accident. Picking a tag adds/removes memberships and reports the count.
 */
export function TagActionBar({
  portfolioId,
  mode,
  selectedIds,
  selectAllMatching,
  hasActiveFilters,
  filterGroups,
  matchingCount,
  allLoadedSelected,
  moreMatchThanLoaded,
  onSelectAllMatching,
  onClearSelection,
  onClose,
}: {
  portfolioId: string;
  mode: TagMode;
  selectedIds: string[];
  selectAllMatching: boolean;
  hasActiveFilters: boolean;
  filterGroups: FilterGroups;
  matchingCount: number;
  allLoadedSelected: boolean;
  moreMatchThanLoaded: boolean;
  onSelectAllMatching: () => void;
  onClearSelection: () => void;
  onClose: () => void;
}) {
  const { data: tags = [] } = usePortfolioTags(portfolioId);
  const invalidate = useInvalidateTagSurfaces(portfolioId);
  const [result, setResult] = useState<string | null>(null);

  const action = mode === "assign" ? "add" : "remove";
  const verb = mode === "assign" ? "Assign" : "Remove";
  const prep = mode === "assign" ? "to" : "from";

  // The current target — explicit selection only (no implicit "all"). Selecting
  // all matching is a deliberate escalation that switches to the filter path.
  type Target = {
    body:
      | { mode: "properties"; propertyIds: string[] }
      | { mode: "filter"; filterGroups: FilterGroups };
    label: string;
  };
  const target: Target | null = selectAllMatching
    ? {
        body: {
          mode: "filter",
          filterGroups: hasActiveFilters ? filterGroups : [],
        },
        label: hasActiveFilters
          ? `all ${matchingCount.toLocaleString()} matching your filter`
          : `all ${matchingCount.toLocaleString()} properties`,
      }
    : selectedIds.length > 0
      ? {
          body: { mode: "properties", propertyIds: selectedIds },
          label: `${selectedIds.length.toLocaleString()} selected propert${selectedIds.length === 1 ? "y" : "ies"}`,
        }
      : null;

  const apply = useMutation<{ changed: number }, Error, Tag>({
    mutationFn: async (tag) => {
      if (!target) throw new Error("Select some properties first");
      const res = await fetch(
        `/api/portfolio/${portfolioId}/tags/${tag.id}/assignments`,
        {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ ...target.body, action }),
        },
      );
      const body = await res.json();
      if (!res.ok) throw new Error(body.error ?? "Couldn't update tags");
      return body;
    },
    onSuccess: (data, tag) => {
      setResult(
        `${mode === "assign" ? "Added" : "Removed"} “${tag.name}” ${prep} ${data.changed.toLocaleString()} propert${data.changed === 1 ? "y" : "ies"}.`,
      );
      invalidate();
    },
    onError: (e) => setResult(e.message),
  });

  const showEscalate =
    !selectAllMatching && allLoadedSelected && moreMatchThanLoaded;

  return (
    <div className="mb-3 flex flex-wrap items-center gap-2.5 rounded-lg border border-brandmidblue/30 bg-brandlightblue/40 px-3 py-2">
      <span className="text-xs font-bold text-brandblue">{verb} a tag</span>

      <span className="text-xs text-slate-600">
        {target ? (
          <>
            {prep}{" "}
            <span className="font-semibold text-brandblue">{target.label}</span>
          </>
        ) : (
          <span className="text-slate-500">
            Tick properties to {mode === "assign" ? "tag" : "untag"} them
          </span>
        )}
      </span>

      {/* Deliberate escalation to the whole matching set (Gmail pattern) —
          a clear secondary button (white fill + brand border) so it stands out
          on the tinted bar without competing with the navy "Choose a tag". */}
      {showEscalate && (
        <button
          onClick={onSelectAllMatching}
          className="inline-flex items-center gap-1 rounded-lg border border-brandmidblue bg-white px-2.5 py-1 text-xs font-semibold text-brandblue shadow-sm transition hover:bg-brandmidblue hover:text-white"
        >
          <CheckIcon className="h-3.5 w-3.5" />
          Select all {matchingCount.toLocaleString()}
          {hasActiveFilters ? " matching" : ""}
        </button>
      )}
      {selectAllMatching && (
        <button
          onClick={onClearSelection}
          className="text-xs font-semibold text-slate-600 underline underline-offset-2 hover:text-brandblue"
        >
          Clear selection
        </button>
      )}

      <DropdownMenu>
        <DropdownMenuTrigger asChild>
          <button
            disabled={apply.isLoading || !target}
            className="inline-flex items-center gap-1.5 rounded-lg bg-primary px-3 py-1.5 text-xs font-semibold text-white transition hover:opacity-90 disabled:cursor-not-allowed disabled:opacity-40"
          >
            {apply.isLoading ? "Applying…" : "Choose a tag"}
            <ChevronDownIcon className="h-3.5 w-3.5 opacity-70" />
          </button>
        </DropdownMenuTrigger>
        <DropdownMenuContent align="start" className="max-h-72 w-56 overflow-y-auto">
          <DropdownMenuLabel className="text-xs">
            {verb} which tag?
          </DropdownMenuLabel>
          <DropdownMenuSeparator />
          {tags.length === 0 ? (
            <div className="px-2 py-2 text-xs text-slate-400">
              No tags yet.{" "}
              <a
                href={`/portfolio/${portfolioId}/settings/tags`}
                className="font-semibold text-brandmidblue hover:underline"
              >
                Create one
              </a>
              .
            </div>
          ) : (
            tags.map((t) => (
              <DropdownMenuItem
                key={t.id}
                className="flex cursor-pointer items-center gap-2"
                onSelect={() => apply.mutate(t)}
              >
                <span
                  className="h-3 w-3 shrink-0 rounded-full border"
                  style={{ backgroundColor: tagDotColour(t.colour) }}
                />
                <span className="truncate text-xs">{t.name}</span>
              </DropdownMenuItem>
            ))
          )}
        </DropdownMenuContent>
      </DropdownMenu>

      {result && (
        <span className="rounded-lg border border-emerald-200 bg-emerald-50 px-2.5 py-1 text-xs text-emerald-800">
          {result}
        </span>
      )}

      <button
        onClick={onClose}
        className="ml-auto inline-flex items-center gap-1 rounded-md px-2 py-1 text-xs font-semibold text-slate-500 hover:text-brandblue"
      >
        <XMarkIcon className="h-3.5 w-3.5" />
        Done
      </button>
    </div>
  );
}
