import { KbdHint } from "@client/components/KbdHint";
import { getDisplayKey, SHORTCUTS } from "@client/lib/shortcut-map";
import { formatCountryLabel } from "@shared/location-support";
import {
  SPONSORSHIP_GREEN_FLAG_IDS,
  SPONSORSHIP_RED_FLAG_IDS,
  SPONSORSHIP_SIGNAL_META,
  SPONSORSHIP_YELLOW_FLAG_IDS,
  type SponsorshipSignalId,
} from "@shared/sponsorship-signals";
import type { JobSource } from "@shared/types.js";
import { Filter, Search } from "lucide-react";
import type React from "react";
import { useMemo, useState } from "react";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Checkbox } from "@/components/ui/checkbox";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { Separator } from "@/components/ui/separator";
import {
  Sheet,
  SheetContent,
  SheetDescription,
  SheetHeader,
  SheetTitle,
  SheetTrigger,
} from "@/components/ui/sheet";
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { sourceLabel } from "@/lib/utils";
import type {
  FilterTab,
  JobSort,
  SalaryFilter,
  SalaryFilterMode,
  SponsorFilter,
  WorkplaceFilter,
} from "./constants";
import { defaultSortDirection, orderedFilterSources, tabs } from "./constants";
import { TokenizedInput } from "./TokenizedInput";

interface OrchestratorFiltersProps {
  activeTab: FilterTab;
  onTabChange: (value: FilterTab) => void;
  counts: Record<FilterTab, number>;
  onOpenCommandBar: () => void;
  sourcesFilter: JobSource[];
  sourcesExcludeFilter: JobSource[];
  onSourceSelectionChange: (include: JobSource[], exclude: JobSource[]) => void;
  countriesFilter: string[];
  countriesExcludeFilter: string[];
  onCountrySelectionChange: (include: string[], exclude: string[]) => void;
  foundAfterYmd: string | null;
  foundBeforeYmd: string | null;
  onFoundDateRangeChange: (
    foundAfter: string | null,
    foundBefore: string | null,
  ) => void;
  employerIncludeFilter: string[];
  employerExcludeFilter: string[];
  onEmployerIncludeChange: (values: string[]) => void;
  onEmployerExcludeChange: (values: string[]) => void;
  applySettingsCompanySkipList: boolean;
  onApplySettingsCompanySkipListChange: (value: boolean) => void;
  hidePriorSkips: boolean;
  onHidePriorSkipsChange: (value: boolean) => void;
  sponsorFilter: SponsorFilter;
  onSponsorFilterChange: (value: SponsorFilter) => void;
  sponsorshipSignalsFilter: SponsorshipSignalId[];
  onSponsorshipSignalsFilterChange: (values: SponsorshipSignalId[]) => void;
  hideSponsorBlockers: boolean;
  onHideSponsorBlockersChange: (value: boolean) => void;
  workplaceFilter: WorkplaceFilter;
  onWorkplaceFilterChange: (value: WorkplaceFilter) => void;
  salaryFilter: SalaryFilter;
  onSalaryFilterChange: (value: SalaryFilter) => void;
  sourcesWithJobs: JobSource[];
  countriesWithJobs: string[];
  sort: JobSort;
  onSortChange: (sort: JobSort) => void;
  onResetFilters: () => void;
  filteredCount: number;
  isFiltersOpen?: boolean;
  onFiltersOpenChange?: (open: boolean) => void;
}

const workplaceOptions: Array<{
  value: WorkplaceFilter;
  label: string;
}> = [
  { value: "all", label: "All" },
  { value: "remote", label: "Remote" },
  { value: "not_remote", label: "Not remote" },
  { value: "unknown", label: "Unknown" },
];

const sponsorOptions: Array<{
  value: SponsorFilter;
  label: string;
}> = [
  { value: "all", label: "All statuses" },
  { value: "confirmed", label: "Confirmed sponsor" },
  { value: "potential", label: "Potential sponsor" },
  { value: "not_found", label: "Sponsor not found" },
  { value: "unknown", label: "Unchecked sponsor" },
];

const salaryModeOptions: Array<{
  value: SalaryFilterMode;
  label: string;
}> = [
  { value: "at_least", label: "at least" },
  { value: "at_most", label: "at most" },
  { value: "between", label: "between" },
];

const sortFieldOrder: JobSort["key"][] = [
  "score",
  "discoveredAt",
  "salary",
  "title",
  "employer",
];

const sortFieldLabels: Record<JobSort["key"], string> = {
  score: "Score",
  discoveredAt: "Discovered",
  salary: "Salary",
  title: "Title",
  employer: "Company",
};

function parseEmployerTokenInput(input: string): string[] {
  return input
    .split(/[\n,]/g)
    .map((value) => value.trim())
    .filter(Boolean);
}

const getDirectionOptions = (
  key: JobSort["key"],
): Array<{ value: JobSort["direction"]; label: string }> => {
  if (key === "discoveredAt") {
    return [
      { value: "desc", label: "newest first" },
      { value: "asc", label: "oldest first" },
    ];
  }
  if (key === "score" || key === "salary") {
    return [
      { value: "desc", label: "largest first" },
      { value: "asc", label: "smallest first" },
    ];
  }
  return [
    { value: "asc", label: "A to Z" },
    { value: "desc", label: "Z to A" },
  ];
};

export const OrchestratorFilters: React.FC<OrchestratorFiltersProps> = ({
  activeTab,
  onTabChange,
  counts,
  onOpenCommandBar,
  sourcesFilter,
  sourcesExcludeFilter,
  onSourceSelectionChange,
  countriesFilter,
  countriesExcludeFilter,
  onCountrySelectionChange,
  foundAfterYmd,
  foundBeforeYmd,
  onFoundDateRangeChange,
  employerIncludeFilter,
  employerExcludeFilter,
  onEmployerIncludeChange,
  onEmployerExcludeChange,
  applySettingsCompanySkipList,
  onApplySettingsCompanySkipListChange,
  hidePriorSkips,
  onHidePriorSkipsChange,
  sponsorFilter,
  onSponsorFilterChange,
  sponsorshipSignalsFilter,
  onSponsorshipSignalsFilterChange,
  hideSponsorBlockers,
  onHideSponsorBlockersChange,
  workplaceFilter,
  onWorkplaceFilterChange,
  salaryFilter,
  onSalaryFilterChange,
  sourcesWithJobs,
  countriesWithJobs,
  sort,
  onSortChange,
  onResetFilters,
  filteredCount,
  isFiltersOpen: isFiltersOpenProp,
  onFiltersOpenChange: onFiltersOpenChangeProp,
}) => {
  const [internalOpen, setInternalOpen] = useState(false);
  const isFiltersOpen = isFiltersOpenProp ?? internalOpen;
  const onFiltersOpenChange = onFiltersOpenChangeProp ?? setInternalOpen;
  const [employerIncludeDraft, setEmployerIncludeDraft] = useState("");
  const [employerExcludeDraft, setEmployerExcludeDraft] = useState("");

  const visibleSources = orderedFilterSources.filter((source) =>
    sourcesWithJobs.includes(source),
  );

  const cycleSource = (source: JobSource) => {
    const inInclude = sourcesFilter.includes(source);
    const inExclude = sourcesExcludeFilter.includes(source);
    let nextInclude = [...sourcesFilter];
    let nextExclude = [...sourcesExcludeFilter];
    if (!inInclude && !inExclude) {
      nextInclude.push(source);
    } else if (inInclude) {
      nextInclude = nextInclude.filter((value) => value !== source);
      nextExclude.push(source);
    } else {
      nextExclude = nextExclude.filter((value) => value !== source);
    }
    onSourceSelectionChange(nextInclude, nextExclude);
  };

  const cycleCountry = (countryKey: string) => {
    const inInclude = countriesFilter.includes(countryKey);
    const inExclude = countriesExcludeFilter.includes(countryKey);
    let nextInclude = [...countriesFilter];
    let nextExclude = [...countriesExcludeFilter];
    if (!inInclude && !inExclude) {
      nextInclude.push(countryKey);
    } else if (inInclude) {
      nextInclude = nextInclude.filter((value) => value !== countryKey);
      nextExclude.push(countryKey);
    } else {
      nextExclude = nextExclude.filter((value) => value !== countryKey);
    }
    onCountrySelectionChange(nextInclude, nextExclude);
  };

  const activeFilterCount = useMemo(
    () =>
      Number(sourcesFilter.length > 0 || sourcesExcludeFilter.length > 0) +
      Number(countriesFilter.length > 0 || countriesExcludeFilter.length > 0) +
      Number(Boolean(foundAfterYmd) || Boolean(foundBeforeYmd)) +
      Number(
        employerIncludeFilter.length > 0 || employerExcludeFilter.length > 0,
      ) +
      Number(!applySettingsCompanySkipList) +
      Number(!hidePriorSkips) +
      Number(sponsorFilter !== "all") +
      Number(sponsorshipSignalsFilter.length > 0) +
      Number(hideSponsorBlockers) +
      Number(workplaceFilter !== "all") +
      Number(
        (typeof salaryFilter.min === "number" && salaryFilter.min > 0) ||
          (typeof salaryFilter.max === "number" && salaryFilter.max > 0),
      ),
    [
      sourcesFilter.length,
      sourcesExcludeFilter.length,
      countriesFilter.length,
      countriesExcludeFilter.length,
      foundAfterYmd,
      foundBeforeYmd,
      employerIncludeFilter.length,
      employerExcludeFilter.length,
      applySettingsCompanySkipList,
      hidePriorSkips,
      sponsorFilter,
      sponsorshipSignalsFilter.length,
      hideSponsorBlockers,
      workplaceFilter,
      salaryFilter.min,
      salaryFilter.max,
    ],
  );
  const showSalaryMin =
    salaryFilter.mode === "at_least" || salaryFilter.mode === "between";
  const showSalaryMax =
    salaryFilter.mode === "at_most" || salaryFilter.mode === "between";
  const commandShortcutLabel = getDisplayKey(SHORTCUTS.search);

  return (
    <Tabs
      value={activeTab}
      onValueChange={(value) => onTabChange(value as FilterTab)}
    >
      <div className="flex flex-col gap-3 lg:flex-row lg:items-center lg:justify-between">
        <TabsList className="h-auto w-full flex-wrap justify-start gap-1 lg:w-auto">
          {tabs.map((tab, index) => (
            <TabsTrigger
              key={tab.id}
              value={tab.id}
              className="flex-1 flex items-center lg:flex-none gap-1.5"
            >
              <KbdHint shortcut={String(index + 1)} className="mr-0.5" />
              <span>{tab.label}</span>
              {counts[tab.id] > 0 && (
                <span className="text-[10px] mt-[2px] tabular-nums opacity-60">
                  {counts[tab.id]}
                </span>
              )}
            </TabsTrigger>
          ))}
        </TabsList>

        <div className="flex lg:flex-nowrap flex-wrap items-center justify-end gap-2">
          <Button
            type="button"
            variant="ghost"
            size="sm"
            onClick={onOpenCommandBar}
            aria-label="Search jobs"
            className="h-8 gap-1.5 text-xs text-muted-foreground hover:text-foreground w-auto"
          >
            <Search className="h-3.5 w-3.5" />
            Search
            <span className="rounded border border-border/70 px-1 py-0.5 font-mono text-xs leading-none text-muted-foreground">
              {commandShortcutLabel}
            </span>
          </Button>

          <Sheet open={isFiltersOpen} onOpenChange={onFiltersOpenChange}>
            <SheetTrigger asChild>
              <Button
                variant="ghost"
                size="sm"
                className="h-8 gap-1.5 text-xs text-muted-foreground hover:text-foreground w-auto"
              >
                <Filter className="h-3.5 w-3.5" />
                Filters
                {activeFilterCount > 0 && (
                  <span className="inline-flex h-4 min-w-4 items-center justify-center rounded-full bg-primary/20 px-1 text-[10px] font-semibold tabular-nums text-primary">
                    {activeFilterCount}
                  </span>
                )}
              </Button>
            </SheetTrigger>

            <SheetContent side="right" className="w-full sm:max-w-2xl">
              <div className="flex h-full min-h-0 flex-col">
                <SheetHeader>
                  <SheetTitle className="flex items-center gap-2">
                    Filters
                    {activeFilterCount > 0 && (
                      <span className="inline-flex h-5 min-w-5 items-center justify-center rounded-full bg-primary/20 px-1 text-[11px] font-semibold tabular-nums text-primary">
                        {activeFilterCount}
                      </span>
                    )}
                  </SheetTitle>
                  <SheetDescription>
                    Refine sources and country: each button cycles off → include
                    → exclude (red). Remote listings always bypass country
                    filters. Filter by when the job was discovered in JobOps,
                    employer keywords, sponsor, workplace, salary, and sort
                    below.
                  </SheetDescription>
                </SheetHeader>

                <Separator className="my-4" />

                <div className="min-h-0 flex-1 space-y-4 overflow-y-auto pr-1">
                  <Card>
                    <CardHeader className="pb-3">
                      <CardTitle>Sources</CardTitle>
                    </CardHeader>
                    <CardContent className="flex flex-wrap gap-2">
                      <Button
                        type="button"
                        size="sm"
                        variant={
                          sourcesFilter.length === 0 &&
                          sourcesExcludeFilter.length === 0
                            ? "default"
                            : "outline"
                        }
                        onClick={() => onSourceSelectionChange([], [])}
                      >
                        All sources
                      </Button>
                      {visibleSources.map((source) => {
                        const excluded = sourcesExcludeFilter.includes(source);
                        const included = sourcesFilter.includes(source);
                        return (
                          <Button
                            key={source}
                            type="button"
                            size="sm"
                            variant={
                              excluded
                                ? "destructive"
                                : included
                                  ? "default"
                                  : "outline"
                            }
                            onClick={() => cycleSource(source)}
                          >
                            {sourceLabel[source]}
                          </Button>
                        );
                      })}
                    </CardContent>
                  </Card>

                  <Card>
                    <CardHeader className="pb-3">
                      <CardTitle>Country</CardTitle>
                    </CardHeader>
                    <CardContent className="space-y-2">
                      <p className="text-xs text-muted-foreground">
                        Parsed from each job&apos;s location. Jobs marked remote
                        in the listing always match include and exclude country
                        rules.
                      </p>
                      <div className="flex flex-wrap gap-2">
                        <Button
                          type="button"
                          size="sm"
                          variant={
                            countriesFilter.length === 0 &&
                            countriesExcludeFilter.length === 0
                              ? "default"
                              : "outline"
                          }
                          onClick={() => onCountrySelectionChange([], [])}
                        >
                          All countries
                        </Button>
                        {countriesWithJobs.map((countryKey) => {
                          const excluded =
                            countriesExcludeFilter.includes(countryKey);
                          const included = countriesFilter.includes(countryKey);
                          return (
                            <Button
                              key={countryKey}
                              type="button"
                              size="sm"
                              variant={
                                excluded
                                  ? "destructive"
                                  : included
                                    ? "default"
                                    : "outline"
                              }
                              onClick={() => cycleCountry(countryKey)}
                            >
                              {formatCountryLabel(countryKey)}
                            </Button>
                          );
                        })}
                      </div>
                    </CardContent>
                  </Card>

                  <Card>
                    <CardHeader className="pb-3">
                      <CardTitle>Found in JobOps</CardTitle>
                    </CardHeader>
                    <CardContent className="space-y-3">
                      <p className="text-xs text-muted-foreground">
                        When this listing was first saved during discovery (your
                        local JobOps clock). Leave blank to show all dates.
                      </p>
                      <div className="grid gap-3 sm:grid-cols-2">
                        <div className="space-y-1">
                          <Label htmlFor="found-after-filter">
                            On or after
                          </Label>
                          <Input
                            id="found-after-filter"
                            type="date"
                            value={foundAfterYmd ?? ""}
                            onChange={(event) => {
                              const next = event.target.value;
                              onFoundDateRangeChange(
                                next ? next : null,
                                foundBeforeYmd,
                              );
                            }}
                          />
                        </div>
                        <div className="space-y-1">
                          <Label htmlFor="found-before-filter">
                            On or before
                          </Label>
                          <Input
                            id="found-before-filter"
                            type="date"
                            value={foundBeforeYmd ?? ""}
                            onChange={(event) => {
                              const next = event.target.value;
                              onFoundDateRangeChange(
                                foundAfterYmd,
                                next ? next : null,
                              );
                            }}
                          />
                        </div>
                      </div>
                    </CardContent>
                  </Card>

                  <Card>
                    <CardHeader className="pb-3">
                      <CardTitle>Employer keywords</CardTitle>
                    </CardHeader>
                    <CardContent className="space-y-4">
                      <p className="text-xs text-muted-foreground">
                        Case-insensitive substring match on employer name.
                        Include narrows to rows that match any token; exclude
                        hides matching rows. When enabled, your Settings company
                        skip list is applied here too (not only during
                        discovery).
                      </p>

                      <div className="flex items-start gap-3 rounded-md border border-border/60 bg-muted/20 px-3 py-3">
                        <Checkbox
                          id="apply-settings-company-skip"
                          checked={applySettingsCompanySkipList}
                          onCheckedChange={(checked) => {
                            onApplySettingsCompanySkipListChange(
                              checked === true,
                            );
                          }}
                        />
                        <div className="space-y-1">
                          <label
                            htmlFor="apply-settings-company-skip"
                            className="text-sm font-medium leading-none cursor-pointer"
                          >
                            Apply Settings company skip list
                          </label>
                          <p className="text-xs text-muted-foreground">
                            Uncheck to temporarily show employers blocked in
                            Settings → Scoring (e.g. to clean up old rows).
                          </p>
                        </div>
                      </div>

                      <div className="flex items-start gap-3 rounded-md border border-border/60 bg-muted/20 px-3 py-3">
                        <Checkbox
                          id="hide-prior-skips"
                          checked={hidePriorSkips}
                          onCheckedChange={(checked) => {
                            onHidePriorSkipsChange(checked === true);
                          }}
                        />
                        <div className="space-y-1">
                          <label
                            htmlFor="hide-prior-skips"
                            className="text-sm font-medium leading-none cursor-pointer"
                          >
                            Hide roles you already skipped
                          </label>
                          <p className="text-xs text-muted-foreground">
                            Hides Discovered and Ready rows that match a skipped
                            or applied job with the same company and title from
                            the last 90 days.
                          </p>
                        </div>
                      </div>

                      <TokenizedInput
                        id="employer-include-filter"
                        values={employerIncludeFilter}
                        draft={employerIncludeDraft}
                        parseInput={parseEmployerTokenInput}
                        onDraftChange={setEmployerIncludeDraft}
                        onValuesChange={onEmployerIncludeChange}
                        placeholder="e.g. partial company name"
                        helperText="Only show jobs whose employer contains at least one of these tokens."
                        removeLabelPrefix="Remove include token"
                      />

                      <TokenizedInput
                        id="employer-exclude-filter"
                        values={employerExcludeFilter}
                        draft={employerExcludeDraft}
                        parseInput={parseEmployerTokenInput}
                        onDraftChange={setEmployerExcludeDraft}
                        onValuesChange={onEmployerExcludeChange}
                        placeholder="e.g. agency name"
                        helperText="Hide jobs whose employer contains any of these tokens (in addition to the Settings skip list when enabled above)."
                        removeLabelPrefix="Remove exclude token"
                      />
                    </CardContent>
                  </Card>

                  <Card>
                    <CardHeader className="pb-3">
                      <CardTitle>Sponsor status</CardTitle>
                    </CardHeader>
                    <CardContent className="space-y-4">
                      <div className="flex flex-wrap gap-2">
                        {sponsorOptions.map((option) => (
                          <Button
                            key={option.value}
                            type="button"
                            size="sm"
                            variant={
                              sponsorFilter === option.value
                                ? "default"
                                : "outline"
                            }
                            onClick={() => onSponsorFilterChange(option.value)}
                          >
                            {option.label}
                          </Button>
                        ))}
                      </div>
                      <div className="space-y-3">
                        <div className="flex items-start gap-3 rounded-md border border-border/60 bg-muted/20 px-3 py-3">
                          <Checkbox
                            id="hide-sponsor-blockers"
                            checked={hideSponsorBlockers}
                            onCheckedChange={(checked) => {
                              onHideSponsorBlockersChange(checked === true);
                            }}
                          />
                          <div className="space-y-1">
                            <label
                              htmlFor="hide-sponsor-blockers"
                              className="text-sm font-medium leading-none cursor-pointer"
                            >
                              Hide red-flag roles
                            </label>
                            <p className="text-xs text-muted-foreground">
                              Hides citizenship/GC/EAD-only, clearance, and
                              unrestricted-work-auth posts. Yellow no-sponsor
                              listings stay visible so you can ask about TN.
                            </p>
                          </div>
                        </div>
                        <div className="space-y-2">
                          <p className="text-xs font-medium text-emerald-200/90">
                            Green flags (TN-friendly)
                          </p>
                          <p className="text-xs text-muted-foreground">
                            Show jobs matching any selected signal. Search{" "}
                            <span className="font-mono">TN</span>,{" "}
                            <span className="font-mono">sponsor</span>, or{" "}
                            <span className="font-mono">
                              authorized to work
                            </span>{" "}
                            in the job search bar too.
                          </p>
                          <div className="flex flex-wrap gap-2">
                            {SPONSORSHIP_GREEN_FLAG_IDS.map((signalId) => {
                              const selected =
                                sponsorshipSignalsFilter.includes(signalId);
                              const meta = SPONSORSHIP_SIGNAL_META[signalId];
                              return (
                                <Button
                                  key={signalId}
                                  type="button"
                                  size="sm"
                                  variant={selected ? "default" : "outline"}
                                  onClick={() => {
                                    const next = selected
                                      ? sponsorshipSignalsFilter.filter(
                                          (value) => value !== signalId,
                                        )
                                      : [...sponsorshipSignalsFilter, signalId];
                                    onSponsorshipSignalsFilterChange(next);
                                  }}
                                >
                                  {meta.label}
                                </Button>
                              );
                            })}
                          </div>
                        </div>
                        <div className="space-y-2">
                          <p className="text-xs font-medium text-amber-200/90">
                            Yellow flags (verify TN)
                          </p>
                          <p className="text-xs text-muted-foreground">
                            Says no sponsorship — ask if TN support letter is
                            available.
                          </p>
                          <div className="flex flex-wrap gap-2">
                            {SPONSORSHIP_YELLOW_FLAG_IDS.map((signalId) => {
                              const selected =
                                sponsorshipSignalsFilter.includes(signalId);
                              const meta = SPONSORSHIP_SIGNAL_META[signalId];
                              return (
                                <Button
                                  key={signalId}
                                  type="button"
                                  size="sm"
                                  variant={selected ? "secondary" : "outline"}
                                  className={
                                    selected
                                      ? "border-amber-500/40 bg-amber-500/20 text-amber-100"
                                      : undefined
                                  }
                                  onClick={() => {
                                    const next = selected
                                      ? sponsorshipSignalsFilter.filter(
                                          (value) => value !== signalId,
                                        )
                                      : [...sponsorshipSignalsFilter, signalId];
                                    onSponsorshipSignalsFilterChange(next);
                                  }}
                                >
                                  {meta.label}
                                </Button>
                              );
                            })}
                          </div>
                        </div>
                        <div className="space-y-2">
                          <p className="text-xs font-medium text-rose-200/90">
                            Red flags (hard skip)
                          </p>
                          <p className="text-xs text-muted-foreground">
                            Citizenship/GC/EAD only, clearance, or unrestricted
                            work authorization — usually not TN-viable.
                          </p>
                          <div className="flex flex-wrap gap-2">
                            {SPONSORSHIP_RED_FLAG_IDS.map((signalId) => {
                              const selected =
                                sponsorshipSignalsFilter.includes(signalId);
                              const meta = SPONSORSHIP_SIGNAL_META[signalId];
                              return (
                                <Button
                                  key={signalId}
                                  type="button"
                                  size="sm"
                                  variant={selected ? "destructive" : "outline"}
                                  onClick={() => {
                                    const next = selected
                                      ? sponsorshipSignalsFilter.filter(
                                          (value) => value !== signalId,
                                        )
                                      : [...sponsorshipSignalsFilter, signalId];
                                    onSponsorshipSignalsFilterChange(next);
                                  }}
                                >
                                  {meta.label}
                                </Button>
                              );
                            })}
                          </div>
                        </div>
                      </div>
                    </CardContent>
                  </Card>

                  <Card>
                    <CardHeader className="pb-3">
                      <CardTitle>Workplace</CardTitle>
                    </CardHeader>
                    <CardContent className="space-y-2">
                      <p className="text-xs text-muted-foreground">
                        Based on each listing&apos;s remote flag. Use Unknown
                        when the source did not mark remote vs on-site.
                      </p>
                      <div className="flex flex-wrap gap-2">
                        {workplaceOptions.map((option) => (
                          <Button
                            key={option.value}
                            type="button"
                            size="sm"
                            variant={
                              workplaceFilter === option.value
                                ? "default"
                                : "outline"
                            }
                            onClick={() =>
                              onWorkplaceFilterChange(option.value)
                            }
                          >
                            {option.label}
                          </Button>
                        ))}
                      </div>
                    </CardContent>
                  </Card>

                  <Card>
                    <CardHeader className="pb-3">
                      <CardTitle>Salary</CardTitle>
                    </CardHeader>
                    <CardContent className="space-y-3">
                      <div className="flex flex-wrap items-center gap-2 text-sm text-muted-foreground">
                        <span>Salary is</span>
                        <Select
                          value={salaryFilter.mode}
                          onValueChange={(value) => {
                            const nextMode = value as SalaryFilterMode;
                            if (nextMode === "at_least") {
                              onSalaryFilterChange({
                                mode: nextMode,
                                min: salaryFilter.min,
                                max: null,
                              });
                              return;
                            }
                            if (nextMode === "at_most") {
                              onSalaryFilterChange({
                                mode: nextMode,
                                min: null,
                                max: salaryFilter.max,
                              });
                              return;
                            }
                            onSalaryFilterChange({
                              mode: nextMode,
                              min: salaryFilter.min,
                              max: salaryFilter.max,
                            });
                          }}
                        >
                          <SelectTrigger
                            id="salary-mode"
                            aria-label="Salary range specifier"
                            className="h-8 w-[170px] text-foreground"
                          >
                            <SelectValue />
                          </SelectTrigger>
                          <SelectContent>
                            {salaryModeOptions.map((option) => (
                              <SelectItem
                                key={option.value}
                                value={option.value}
                              >
                                {option.label}
                              </SelectItem>
                            ))}
                          </SelectContent>
                        </Select>
                      </div>

                      <div
                        className={
                          showSalaryMin && showSalaryMax
                            ? "grid gap-3 md:grid-cols-2"
                            : "space-y-3"
                        }
                      >
                        {showSalaryMin && (
                          <div className="space-y-1">
                            <Label htmlFor="salary-min-filter">Minimum</Label>
                            <Input
                              id="salary-min-filter"
                              value={
                                salaryFilter.min == null
                                  ? ""
                                  : String(salaryFilter.min)
                              }
                              onChange={(event) => {
                                const raw = event.target.value.trim();
                                const parsed = Number.parseInt(raw, 10);
                                onSalaryFilterChange({
                                  ...salaryFilter,
                                  min:
                                    Number.isFinite(parsed) && parsed > 0
                                      ? parsed
                                      : null,
                                });
                              }}
                              inputMode="numeric"
                              placeholder="e.g. 60000"
                            />
                          </div>
                        )}

                        {showSalaryMax && (
                          <div className="space-y-1">
                            <Label htmlFor="salary-max-filter">Maximum</Label>
                            <Input
                              id="salary-max-filter"
                              value={
                                salaryFilter.max == null
                                  ? ""
                                  : String(salaryFilter.max)
                              }
                              onChange={(event) => {
                                const raw = event.target.value.trim();
                                const parsed = Number.parseInt(raw, 10);
                                onSalaryFilterChange({
                                  ...salaryFilter,
                                  max:
                                    Number.isFinite(parsed) && parsed > 0
                                      ? parsed
                                      : null,
                                });
                              }}
                              inputMode="numeric"
                              placeholder="e.g. 100000"
                            />
                          </div>
                        )}
                      </div>
                    </CardContent>
                  </Card>

                  <Card>
                    <CardHeader className="pb-3">
                      <CardTitle>Sort</CardTitle>
                    </CardHeader>
                    <CardContent className="space-y-3">
                      <div className="flex flex-col gap-2 text-sm text-muted-foreground sm:flex-row sm:flex-wrap sm:items-center">
                        <div className="flex items-center gap-2">
                          <span className="whitespace-nowrap">Sort by</span>
                          <Select
                            value={sort.key}
                            onValueChange={(value) =>
                              onSortChange({
                                key: value as JobSort["key"],
                                direction:
                                  defaultSortDirection[value as JobSort["key"]],
                              })
                            }
                          >
                            <SelectTrigger
                              id="sort-key"
                              aria-label="Sort field"
                              className="h-8 flex-1 sm:w-[180px] text-foreground"
                            >
                              <SelectValue
                                placeholder={sortFieldLabels[sort.key]}
                              />
                            </SelectTrigger>
                            <SelectContent>
                              {sortFieldOrder.map((key) => (
                                <SelectItem key={key} value={key}>
                                  {sortFieldLabels[key]}
                                </SelectItem>
                              ))}
                            </SelectContent>
                          </Select>
                        </div>

                        <div className="flex items-center gap-2">
                          <span className="whitespace-nowrap">and</span>
                          <Select
                            value={sort.direction}
                            onValueChange={(value) =>
                              onSortChange({
                                ...sort,
                                direction: value as JobSort["direction"],
                              })
                            }
                          >
                            <SelectTrigger
                              id="sort-direction"
                              aria-label="Sort order"
                              className="h-8 flex-1 sm:w-[180px] text-foreground"
                            >
                              <SelectValue
                                placeholder={
                                  getDirectionOptions(sort.key).find(
                                    (option) => option.value === sort.direction,
                                  )?.label
                                }
                              />
                            </SelectTrigger>
                            <SelectContent>
                              {getDirectionOptions(sort.key).map((option) => (
                                <SelectItem
                                  key={option.value}
                                  value={option.value}
                                >
                                  {option.label}
                                </SelectItem>
                              ))}
                            </SelectContent>
                          </Select>
                        </div>
                      </div>
                    </CardContent>
                  </Card>
                </div>

                <div className="mt-3 flex shrink-0 items-center justify-between border-t border-border/60 bg-background pt-3">
                  <Button
                    type="button"
                    variant="outline"
                    onClick={onResetFilters}
                  >
                    Reset
                  </Button>
                  <Button
                    type="button"
                    onClick={() => onFiltersOpenChange?.(false)}
                  >
                    Show {filteredCount.toLocaleString()}{" "}
                    {filteredCount === 1 ? "job" : "jobs"}
                  </Button>
                </div>
              </div>
            </SheetContent>
          </Sheet>
        </div>
      </div>
    </Tabs>
  );
};
