"use client";

import { createPortal } from "react-dom";
import { useMemo, useState, type ReactNode } from "react";
import { InfoTooltip } from "~/components/ui/InfoTooltip.js";
import { useAnchoredOverlay } from "~/hooks/useAnchoredOverlay.js";
import { useReferenceData } from "~/hooks/useReferenceData.js";
import { trpc } from "~/lib/trpc/client.js";
import type { TimelineFilters } from "./TimelineFilter.js";

function TimelineFilterDropdown({
  label,
  children,
  widthClassName = "w-80",
  buttonClassName = "min-w-44",
  tooltipContent,
}: {
  label: string;
  children: ReactNode;
  widthClassName?: string;
  buttonClassName?: string;
  tooltipContent?: ReactNode;
}) {
  const [isOpen, setIsOpen] = useState(false);
  const { triggerRef, panelRef, position, handleOpenChange } = useAnchoredOverlay<HTMLDivElement>({
    open: isOpen,
    onClose: () => setIsOpen(false),
    matchTriggerWidth: true,
  });

  return (
    <div ref={triggerRef} className="relative">
      <div className="flex items-center gap-2">
        <button
          type="button"
          onClick={() => {
            const nextOpen = !isOpen;
            handleOpenChange(nextOpen);
            setIsOpen(nextOpen);
          }}
          className={`inline-flex items-center justify-between gap-3 rounded-xl border border-gray-300 bg-white px-3 py-2 text-sm text-gray-700 shadow-sm transition hover:border-gray-400 hover:bg-gray-50 dark:border-gray-600 dark:bg-gray-900 dark:text-gray-200 dark:hover:bg-gray-800 ${buttonClassName}`}
        >
          <span className="text-left">{label}</span>
          <span className="text-xs text-gray-400 dark:text-gray-500">{isOpen ? "▲" : "▼"}</span>
        </button>
        {tooltipContent ? <InfoTooltip content={tooltipContent} width="w-72" /> : null}
      </div>
      {isOpen &&
        createPortal(
          <div
            ref={panelRef}
            style={{
              position: "fixed",
              top: position.top,
              left: position.left,
              minWidth: position.minWidth,
            }}
            className={`z-[9998] rounded-2xl border border-gray-200 bg-white p-3 shadow-xl dark:border-gray-700 dark:bg-gray-900 ${widthClassName}`}
          >
            {children}
          </div>,
          document.body,
        )}
    </div>
  );
}

function FilterChip({ label, onRemove }: { label: string; onRemove: () => void }) {
  return (
    <span className="inline-flex items-center gap-1 rounded-full border border-brand-200 bg-brand-50 px-2 py-0.5 text-xs font-medium text-brand-700 dark:border-brand-800 dark:bg-brand-950/40 dark:text-brand-200">
      {label}
      <button
        type="button"
        onClick={onRemove}
        className="leading-none text-brand-400 hover:text-brand-700 dark:hover:text-brand-100"
      >
        ×
      </button>
    </span>
  );
}

function buildSelectionLabel(prefix: string, selectedCount: number, totalCount: number) {
  if (selectedCount === 0) return `All ${prefix}`;
  return `${prefix}: ${selectedCount}/${totalCount}`;
}

type ResourceOption = {
  id: string;
  eid: string;
  displayName: string;
  chapter: string | null;
};

type ClientOption = {
  id: string;
  name: string;
  code: string | null;
  isActive?: boolean;
};

interface TimelineQuickFiltersProps {
  filters: TimelineFilters;
  onChange: (filters: TimelineFilters) => void;
}

export function TimelineQuickFilters({ filters, onChange }: TimelineQuickFiltersProps) {
  const [eidSearch, setEidSearch] = useState("");
  const { clients, countries } = useReferenceData({ clients: true, countries: true });
  const { data: resourceData } = trpc.resource.directory.useQuery(
    { isActive: true, limit: 500 },
    { staleTime: 60_000 },
  );
  const { data: eidSearchData } = trpc.resource.directory.useQuery(
    { isActive: true, search: eidSearch, limit: 100 },
    { staleTime: 15_000 },
  );
  const resources = ((resourceData?.resources as ResourceOption[] | undefined) ?? []).slice();
  const eidSuggestions = (
    (eidSearchData?.resources as ResourceOption[] | undefined) ??
    resources
  ).filter((resource) => !filters.eids.includes(resource.eid));

  const chapters = useMemo(
    () =>
      [
        ...new Set(
          resources
            .map((resource) => resource.chapter)
            .filter((chapter): chapter is string => Boolean(chapter)),
        ),
      ].sort((left, right) => left.localeCompare(right)),
    [resources],
  );

  const resourceMap = useMemo(
    () => new Map(resources.map((resource) => [resource.eid, resource])),
    [resources],
  );
  const clientMap = useMemo(
    () => new Map(clients.map((client) => [client.id, client])),
    [clients],
  );
  const countryMap = useMemo(
    () => new Map(countries.map((c) => [c.code, c])),
    [countries],
  );

  const clientLabel = buildSelectionLabel("Clients", filters.clientIds.length, clients.length || 1);
  const chapterLabel = buildSelectionLabel(
    "Chapters",
    filters.chapters.length,
    chapters.length || 1,
  );
  const countryLabel = buildSelectionLabel(
    "Countries",
    filters.countryCodes.length,
    countries.length || 1,
  );
  const peopleLabel =
    filters.eids.length === 0 ? "All people" : `People: ${filters.eids.length}`;

  function toggleClient(clientId: string) {
    const nextClientIds = filters.clientIds.includes(clientId)
      ? filters.clientIds.filter((id) => id !== clientId)
      : [...filters.clientIds, clientId].sort((left, right) => {
          const leftName = clientMap.get(left)?.name ?? left;
          const rightName = clientMap.get(right)?.name ?? right;
          return leftName.localeCompare(rightName);
        });
    onChange({ ...filters, clientIds: nextClientIds });
  }

  function toggleChapter(chapter: string) {
    const nextChapters = filters.chapters.includes(chapter)
      ? filters.chapters.filter((value) => value !== chapter)
      : [...filters.chapters, chapter].sort((left, right) => left.localeCompare(right));
    onChange({ ...filters, chapters: nextChapters });
  }

  function toggleCountry(code: string) {
    const next = filters.countryCodes.includes(code)
      ? filters.countryCodes.filter((c) => c !== code)
      : [...filters.countryCodes, code].sort((a, b) => {
          const aName = countryMap.get(a)?.name ?? a;
          const bName = countryMap.get(b)?.name ?? b;
          return aName.localeCompare(bName);
        });
    onChange({ ...filters, countryCodes: next });
  }

  function addEid(eid: string) {
    if (filters.eids.includes(eid)) return;
    onChange({ ...filters, eids: [...filters.eids, eid] });
    setEidSearch("");
  }

  function removeEid(eid: string) {
    onChange({ ...filters, eids: filters.eids.filter((value) => value !== eid) });
  }

  return (
    <>
      <TimelineFilterDropdown
        label={clientLabel}
        widthClassName="w-80"
        tooltipContent="Multi-select project client filter. Checked clients stay visible in both resource and project views."
      >
        <div className="mb-3 flex items-start justify-between gap-3">
          <div>
            <h2 className="text-sm font-semibold text-gray-900 dark:text-gray-100">Clients</h2>
            <p className="text-xs text-gray-500">Checked clients stay visible.</p>
          </div>
          <button
            type="button"
            onClick={() => onChange({ ...filters, clientIds: [] })}
            className="text-xs font-medium text-brand-600 hover:text-brand-800 dark:text-brand-300 dark:hover:text-brand-100"
          >
            Show all
          </button>
        </div>
        <div className="rounded-xl border border-gray-200 dark:border-gray-700">
          <label className="flex items-center gap-3 border-b border-gray-200 px-3 py-2 text-sm text-gray-700 dark:border-gray-700 dark:text-gray-200">
            <input
              type="checkbox"
              checked={filters.clientIds.length === 0}
              ref={(el) => {
                if (el) el.indeterminate = filters.clientIds.length > 0 && filters.clientIds.length < clients.length;
              }}
              onChange={() => {
                // Toggle all ↔ none: if showing all → select all explicitly; if any selected → clear filter (show all)
                onChange({ ...filters, clientIds: filters.clientIds.length === 0 ? clients.map((c) => c.id) : [] });
              }}
              className="h-4 w-4 rounded border-gray-300 text-brand-600 focus:ring-brand-500 dark:border-gray-600"
            />
            <span className="font-medium">All clients</span>
          </label>
          <div className="max-h-64 overflow-auto">
            {clients.map((client) => (
              <label
                key={client.id}
                className="flex items-center gap-3 border-b border-gray-100 px-3 py-2 text-sm text-gray-700 last:border-b-0 hover:bg-gray-50 dark:border-gray-800 dark:text-gray-200 dark:hover:bg-gray-800"
              >
                <input
                  type="checkbox"
                  checked={filters.clientIds.length === 0 || filters.clientIds.includes(client.id)}
                  onChange={() => toggleClient(client.id)}
                  className="h-4 w-4 rounded border-gray-300 text-brand-600 focus:ring-brand-500 dark:border-gray-600"
                />
                <span className="min-w-0 flex-1 truncate">{client.name}</span>
                {client.code ? (
                  <span className="flex-shrink-0 text-xs text-gray-400 dark:text-gray-500">
                    {client.code}
                  </span>
                ) : null}
              </label>
            ))}
          </div>
        </div>
      </TimelineFilterDropdown>

      <TimelineFilterDropdown
        label={chapterLabel}
        widthClassName="w-80"
        tooltipContent="Multi-select resource chapter filter. Checked chapters stay visible in both timeline views."
      >
        <div className="mb-3 flex items-start justify-between gap-3">
          <div>
            <h2 className="text-sm font-semibold text-gray-900 dark:text-gray-100">Chapters</h2>
            <p className="text-xs text-gray-500">Checked chapters stay visible.</p>
          </div>
          <button
            type="button"
            onClick={() => onChange({ ...filters, chapters: [] })}
            className="text-xs font-medium text-brand-600 hover:text-brand-800 dark:text-brand-300 dark:hover:text-brand-100"
          >
            Show all
          </button>
        </div>
        <div className="rounded-xl border border-gray-200 dark:border-gray-700">
          <label className="flex items-center gap-3 border-b border-gray-200 px-3 py-2 text-sm text-gray-700 dark:border-gray-700 dark:text-gray-200">
            <input
              type="checkbox"
              checked={filters.chapters.length === 0}
              onChange={() => onChange({ ...filters, chapters: [] })}
              className="h-4 w-4 rounded border-gray-300 text-brand-600 focus:ring-brand-500 dark:border-gray-600"
            />
            <span className="font-medium">All chapters</span>
          </label>
          <div className="max-h-64 overflow-auto">
            {chapters.map((chapter) => (
              <label
                key={chapter}
                className="flex items-center gap-3 border-b border-gray-100 px-3 py-2 text-sm text-gray-700 last:border-b-0 hover:bg-gray-50 dark:border-gray-800 dark:text-gray-200 dark:hover:bg-gray-800"
              >
                <input
                  type="checkbox"
                  checked={filters.chapters.length === 0 || filters.chapters.includes(chapter)}
                  onChange={() => toggleChapter(chapter)}
                  className="h-4 w-4 rounded border-gray-300 text-brand-600 focus:ring-brand-500 dark:border-gray-600"
                />
                <span>{chapter}</span>
              </label>
            ))}
          </div>
        </div>
      </TimelineFilterDropdown>

      <TimelineFilterDropdown
        label={countryLabel}
        widthClassName="w-80"
        tooltipContent="Multi-select country filter. Checked countries stay visible in both timeline views."
      >
        <div className="mb-3 flex items-start justify-between gap-3">
          <div>
            <h2 className="text-sm font-semibold text-gray-900 dark:text-gray-100">Countries</h2>
            <p className="text-xs text-gray-500">Checked countries stay visible.</p>
          </div>
          <button
            type="button"
            onClick={() => onChange({ ...filters, countryCodes: [] })}
            className="text-xs font-medium text-brand-600 hover:text-brand-800 dark:text-brand-300 dark:hover:text-brand-100"
          >
            Show all
          </button>
        </div>
        <div className="rounded-xl border border-gray-200 dark:border-gray-700">
          <label className="flex items-center gap-3 border-b border-gray-200 px-3 py-2 text-sm text-gray-700 dark:border-gray-700 dark:text-gray-200">
            <input
              type="checkbox"
              checked={filters.countryCodes.length === 0}
              onChange={() => onChange({ ...filters, countryCodes: [] })}
              className="h-4 w-4 rounded border-gray-300 text-brand-600 focus:ring-brand-500 dark:border-gray-600"
            />
            <span className="font-medium">All countries</span>
          </label>
          <div className="max-h-64 overflow-auto">
            {countries.map((country) => (
              <label
                key={country.code}
                className="flex items-center gap-3 border-b border-gray-100 px-3 py-2 text-sm text-gray-700 last:border-b-0 hover:bg-gray-50 dark:border-gray-800 dark:text-gray-200 dark:hover:bg-gray-800"
              >
                <input
                  type="checkbox"
                  checked={filters.countryCodes.length === 0 || filters.countryCodes.includes(country.code)}
                  onChange={() => toggleCountry(country.code)}
                  className="h-4 w-4 rounded border-gray-300 text-brand-600 focus:ring-brand-500 dark:border-gray-600"
                />
                <span className="min-w-0 flex-1 truncate">{country.name}</span>
                <span className="flex-shrink-0 text-xs text-gray-400 dark:text-gray-500">
                  {country.code}
                </span>
              </label>
            ))}
          </div>
        </div>
      </TimelineFilterDropdown>

      <TimelineFilterDropdown
        label={peopleLabel}
        widthClassName="w-96"
        buttonClassName="min-w-52"
        tooltipContent="Multi-select people filter by displayed EID. Use search to add one or more resources and keep only those people visible."
      >
        <div className="mb-3">
          <div className="flex items-start justify-between gap-3">
            <div>
              <h2 className="text-sm font-semibold text-gray-900 dark:text-gray-100">
                People (EID)
              </h2>
              <p className="text-xs text-gray-500">Search by displayed name or EID.</p>
            </div>
            <button
              type="button"
              onClick={() => onChange({ ...filters, eids: [] })}
              className="text-xs font-medium text-brand-600 hover:text-brand-800 dark:text-brand-300 dark:hover:text-brand-100"
            >
              Clear
            </button>
          </div>
          <div className="mt-2 flex flex-wrap gap-1">
            {filters.eids.map((eid) => {
              const resource = resourceMap.get(eid);
              const label = resource ? `${resource.displayName} (${eid})` : eid;
              return <FilterChip key={eid} label={label} onRemove={() => removeEid(eid)} />;
            })}
          </div>
        </div>
        <div className="relative">
          <input
            type="search"
            placeholder="Search by name or EID..."
            value={eidSearch}
            onChange={(event) => setEidSearch(event.target.value)}
            className="app-input w-full px-2.5 py-1.5 text-xs"
          />
          {eidSuggestions.length > 0 ? (
            <div className="mt-2 max-h-64 overflow-auto rounded-xl border border-gray-200 dark:border-gray-700">
              {eidSuggestions.map((resource) => (
                <button
                  key={resource.id}
                  type="button"
                  onClick={() => addEid(resource.eid)}
                  className="flex w-full items-center gap-3 border-b border-gray-100 px-3 py-2 text-left text-sm text-gray-700 last:border-b-0 hover:bg-gray-50 dark:border-gray-800 dark:text-gray-200 dark:hover:bg-gray-800"
                >
                  <span className="w-24 flex-shrink-0 font-mono text-xs text-gray-500 dark:text-gray-400">
                    {resource.eid}
                  </span>
                  <span className="min-w-0 flex-1 truncate">{resource.displayName}</span>
                  {resource.chapter ? (
                    <span className="flex-shrink-0 text-xs text-gray-400 dark:text-gray-500">
                      {resource.chapter}
                    </span>
                  ) : null}
                </button>
              ))}
            </div>
          ) : (
            <div className="mt-2 rounded-xl border border-dashed border-gray-300 px-3 py-4 text-xs text-gray-500 dark:border-gray-700 dark:text-gray-400">
              No matching people found.
            </div>
          )}
        </div>
      </TimelineFilterDropdown>
    </>
  );
}
