/**
 * Reusable ticket filter/search bar (UI rework #18): a free-text search input
 * plus the multi-select status/priority checkbox facets. Extracted from
 * {@link TicketsPanel} so both the main listing and the {@link TicketPicker}
 * popup share one implementation and stay in sync.
 *
 * Purely controlled/presentational — it holds no state and knows nothing about
 * the gateway; the owner (a view-model or {@link useTicketSearch}) drives every
 * value and toggle. Facet semantics (ticket #12): OR within a facet, AND across;
 * an empty set ⇒ that facet is unconstrained.
 *
 * The assignee filter stays with the main listing (it needs the project's agent
 * roster and is out of the picker's scope), so it is intentionally not here.
 */

import type { TicketPriority, TicketStatus } from "@/domain";
import type { TicketListSort, TicketListSortField } from "@/ports";
import { Button, Input, cn } from "@/shared";
import {
  PriorityBadge,
  StatusBadge,
  TICKET_PRIORITIES,
  TICKET_STATUSES,
  priorityLabel,
  statusLabel,
} from "./ticketMeta";

/** Styling for the sort-field select, matching the panel's other selects. */
const selectClass = cn(
  "h-8 rounded-md bg-raised px-2 text-xs text-content",
  "border border-border outline-none transition-colors",
  "focus:border-primary disabled:cursor-not-allowed disabled:opacity-50",
);

/** Human labels for the sort fields (also the option text). */
const SORT_FIELD_LABEL: Record<TicketListSortField, string> = {
  number: "Numéro",
  priority: "Priorité",
  status: "Statut",
  title: "Titre",
};

const SORT_FIELDS = Object.keys(SORT_FIELD_LABEL) as TicketListSortField[];

export interface TicketFacetsBarProps {
  /** Current free-text search value (controlled). */
  text: string;
  /** Emitted on every keystroke with the raw input value. */
  onTextChange: (text: string) => void;
  /** Currently-selected status facet values. */
  statuses: TicketStatus[];
  /** Currently-selected priority facet values. */
  priorities: TicketPriority[];
  onToggleStatus: (status: TicketStatus) => void;
  onTogglePriority: (priority: TicketPriority) => void;
  /**
   * Clears both facets. When provided, a « Effacer » button appears while any
   * facet is active. Omit to hide the affordance (the caller clears elsewhere).
   */
  onClearFacets?: () => void;
  /** Placeholder for the search input. */
  searchPlaceholder?: string;
  /**
   * Current sort (ticket #21). `undefined` ⇒ the backend's historical order.
   * When {@link onSortChange} is provided, a « Trier par… » control appears.
   */
  sort?: TicketListSort;
  /** Emitted with the next sort, or `undefined` to restore the default order. */
  onSortChange?: (sort: TicketListSort | undefined) => void;
}

export function TicketFacetsBar({
  text,
  onTextChange,
  statuses,
  priorities,
  onToggleStatus,
  onTogglePriority,
  onClearFacets,
  searchPlaceholder = "Search title/description…",
  sort,
  onSortChange,
}: TicketFacetsBarProps) {
  const hasFacets = statuses.length > 0 || priorities.length > 0;
  return (
    <div className="flex flex-col gap-2">
      <Input
        aria-label="search tickets"
        placeholder={searchPlaceholder}
        value={text}
        onChange={(e) => onTextChange(e.target.value)}
      />
      {/* Multi-select facets (ticket #12): OR within a facet, AND across; no
          box ticked ⇒ that facet is unconstrained. */}
      <fieldset
        aria-label="filter by status"
        className="flex flex-wrap items-center gap-x-3 gap-y-1"
      >
        <legend className="mr-1 text-xs font-medium text-muted">Statut</legend>
        {TICKET_STATUSES.map((s) => (
          <label
            key={s}
            className="flex cursor-pointer items-center gap-1.5 text-xs"
          >
            <input
              type="checkbox"
              aria-label={`filter status ${statusLabel(s)}`}
              className="accent-primary"
              checked={statuses.includes(s)}
              onChange={() => onToggleStatus(s)}
            />
            <StatusBadge status={s} />
          </label>
        ))}
      </fieldset>
      <fieldset
        aria-label="filter by priority"
        className="flex flex-wrap items-center gap-x-3 gap-y-1"
      >
        <legend className="mr-1 text-xs font-medium text-muted">
          Priorité
        </legend>
        {TICKET_PRIORITIES.map((p) => (
          <label
            key={p}
            className="flex cursor-pointer items-center gap-1.5 text-xs"
          >
            <input
              type="checkbox"
              aria-label={`filter priority ${priorityLabel(p)}`}
              className="accent-primary"
              checked={priorities.includes(p)}
              onChange={() => onTogglePriority(p)}
            />
            <PriorityBadge priority={p} />
          </label>
        ))}
      </fieldset>
      {/* Sort control (#21): field choice + asc/desc toggle. Absent field ⇒
          the backend keeps its historical order. Grouping-by-sprint stays
          client-side; this sort applies intra-group. */}
      {onSortChange && (
        <div
          aria-label="sort tickets"
          className="flex flex-wrap items-center gap-2"
        >
          <label className="flex items-center gap-1.5 text-xs text-muted">
            Trier par
            <select
              aria-label="sort tickets by"
              className={selectClass}
              value={sort?.field ?? ""}
              onChange={(e) => {
                const field = e.target.value as TicketListSortField | "";
                if (field === "") onSortChange(undefined);
                else onSortChange({ field, direction: sort?.direction ?? "asc" });
              }}
            >
              <option value="">Par défaut</option>
              {SORT_FIELDS.map((f) => (
                <option key={f} value={f}>
                  {SORT_FIELD_LABEL[f]}
                </option>
              ))}
            </select>
          </label>
          {sort && (
            <Button
              size="sm"
              variant="ghost"
              aria-label={`sort direction ${sort.direction === "asc" ? "ascending" : "descending"}`}
              onClick={() =>
                onSortChange({
                  field: sort.field,
                  direction: sort.direction === "asc" ? "desc" : "asc",
                })
              }
            >
              {sort.direction === "asc" ? "Croissant ↑" : "Décroissant ↓"}
            </Button>
          )}
        </div>
      )}
      {onClearFacets && hasFacets && (
        <div>
          <Button
            size="sm"
            variant="ghost"
            aria-label="clear filters"
            onClick={onClearFacets}
          >
            Effacer
          </Button>
        </div>
      )}
    </div>
  );
}
