'use client';

import * as FieldIcons from './Icons';

import Link from 'next/link';
import { useRef, useState, useTransition } from 'react';
import { useRouter } from 'next/navigation';
import { BadgeCheckIcon, ChevronDownIcon, FilterIcon, Spinner, XIcon } from './Icons';

type Facet = { slug: string; name: string; count: number };
export type FilterValues = { city?: string; practiceArea?: string; language?: string; minExperience?: string; verified?: string; sort?: string };

/** Make sure the selected value is selectable even when it fell outside the top-N facet list */
function withSelected(facets: Facet[], selected: string | undefined, label?: string): Facet[] {
  if (!selected || facets.some((f) => f.slug === selected)) return facets;
  return [{ slug: selected, name: label ?? selected, count: 0 }, ...facets];
}

export function SearchFilters({
  q,
  values,
  facets,
  labels,
  clearHref,
}: {
  q: string;
  values: FilterValues;
  facets: { cities: Facet[]; practiceAreas: Facet[]; languages: Facet[] };
  labels: { city?: string; practiceArea?: string; language?: string };
  clearHref: string;
}) {
  const form = useRef<HTMLFormElement>(null);
  const [open, setOpen] = useState(false);
  const [pending, start] = useTransition();
  const router = useRouter();
  const active = [values.city, values.practiceArea, values.language, values.minExperience, values.verified === 'true' ? 'v' : undefined].filter(Boolean).length;

  // Apply as soon as a control changes; the transition keeps the old results visible while loading
  const apply = () => {
    const fd = new FormData(form.current!);
    const qs = new URLSearchParams();
    for (const [k, v] of fd.entries()) if (typeof v === 'string' && v && !(k === 'sort' && v === 'relevance')) qs.set(k, v);
    start(() => router.push(`/search/?${qs}`, { scroll: false }));
  };

  const select = (name: keyof FilterValues, label: string, any: string, list: Facet[]) => (
    <label className="block">
      <span className="field-label"><FieldIcons.FilterIcon />{label}</span>
      <select name={name} defaultValue={values[name] ?? ''} onChange={apply} className="field">
        <option value="">{any}</option>
        {list.map((c) => (
          <option key={c.slug} value={c.slug}>
            {c.name}
            {c.count ? ` (${c.count})` : ''}
          </option>
        ))}
      </select>
    </label>
  );

  return (
    <div>
      <button type="button" onClick={() => setOpen((o) => !o)} aria-expanded={open} aria-controls="search-filters" className="btn btn-quiet w-full justify-between lg:hidden">
        <span className="inline-flex items-center gap-2">
          <FilterIcon className="h-4 w-4" /> Filters
          {active > 0 && <span className="num grid h-5 min-w-5 place-items-center rounded-full bg-ledger px-1.5 text-xs text-ledger-ink">{active}</span>}
        </span>
        <ChevronDownIcon className={`h-4 w-4 transition-transform ${open ? 'rotate-180' : ''}`} />
      </button>

      <form
        // Remount when the URL's filters change (e.g. "Clear"), so uncontrolled selects show the new state
        key={JSON.stringify([q, values])}
        ref={form}
        id="search-filters"
        action="/search/"
        aria-label="Filters"
        onSubmit={(e) => {
          e.preventDefault();
          apply();
        }}
        className={`${open ? 'mt-3 block' : 'hidden'} card sticky-panel space-y-5 p-5 text-sm lg:sticky lg:top-[calc(var(--header-h)+1.5rem)] lg:mt-0 lg:block`}
      >
        <div className="flex items-center justify-between">
          <p className="inline-flex items-center gap-2 font-semibold text-ink">
            <FilterIcon className="h-4 w-4 text-ledger" /> Refine results
          </p>
          {pending && <Spinner className="h-4 w-4 text-ledger" />}
        </div>
        {q && <input type="hidden" name="q" value={q} />}
        {select('city', 'City', 'Any city', withSelected(facets.cities, values.city, labels.city))}
        {select('practiceArea', 'Practice area', 'Any practice area', withSelected(facets.practiceAreas, values.practiceArea, labels.practiceArea))}
        {select('language', 'Language', 'Any language', withSelected(facets.languages, values.language, labels.language))}
        <label className="block">
          <span className="field-label"><FieldIcons.CalendarIcon />Minimum experience</span>
          <select name="minExperience" defaultValue={values.minExperience ?? ''} onChange={apply} className="field">
            <option value="">Any</option>
            {[3, 5, 10, 15, 20].map((n) => (
              <option key={n} value={n}>
                {n}+ years
              </option>
            ))}
          </select>
        </label>
        <label className="flex items-center gap-2.5 rounded-lg border border-rule bg-paper px-3 py-2.5 transition-colors hover:border-rule-strong">
          <input type="checkbox" name="verified" value="true" defaultChecked={values.verified === 'true'} onChange={apply} />
          <BadgeCheckIcon className="h-4 w-4 text-ledger" />
          <span className="font-medium">Verified licence only</span>
        </label>
        <label className="block">
          <span className="field-label"><FieldIcons.FilterIcon />Sort by</span>
          <select name="sort" defaultValue={values.sort ?? 'relevance'} onChange={apply} className="field">
            <option value="relevance">Best match</option>
            <option value="experience">Most experience</option>
            <option value="name">Name (A–Z)</option>
          </select>
        </label>
        <div className="flex gap-2 border-t border-rule pt-4">
          <button className="btn btn-primary btn-sm flex-1" disabled={pending}>
            Apply
          </button>
          <Link href={clearHref} className="btn btn-quiet btn-sm" aria-disabled={active === 0 || undefined}>
            <XIcon className="h-3.5 w-3.5" /> Clear
          </Link>
        </div>
      </form>
    </div>
  );
}
