"use client";

import { useState, useCallback, useTransition, useRef, useEffect } from "react";
import type { ReactNode } from "react";
import { useRouter, useSearchParams, usePathname } from "next/navigation";
import { isValidPostcode } from "@/lib/utils";
import { track } from "@/lib/analytics";
import type { Filters, ResultFilters } from "@/lib/types";
import styles from "./FilterBar.module.css";

interface FilterBarProps {
  filters: Filters;
  isHero?: boolean;
  resultFilters?: ResultFilters;
  // Geolocation "use my location" affordance, shown beside the hero search box.
  // The state and handler live in HomeView (which owns the geolocation flow).
  onNearMe?: () => void;
  geoState?: "idle" | "requesting" | "error";
  geoError?: string | null;
}

/**
 * Wraps a native <select> so the disclosure arrow can be drawn in CSS from
 * currentColor rather than baked into a background image — a hardcoded arrow
 * colour is the one thing in a select that can't follow the theme.
 */
function SelectShell({
  children,
  wide,
}: {
  children: ReactNode;
  wide?: boolean;
}) {
  return (
    <span
      className={`${styles.selectShell}${wide ? ` ${styles.selectShellWide}` : ""}`}
    >
      {children}
      <span className={styles.selectChevron} aria-hidden="true" />
    </span>
  );
}

export function FilterBar({
  filters,
  isHero,
  resultFilters,
  onNearMe,
  geoState = "idle",
  geoError,
}: FilterBarProps) {
  const router = useRouter();
  const pathname = usePathname();
  const searchParams = useSearchParams();
  const [isPending, startTransition] = useTransition();
  const inputRef = useRef<HTMLInputElement>(null);

  const currentSearch = searchParams.get("search") || "";
  const currentPostcode = searchParams.get("postcode") || "";
  const currentRadius = searchParams.get("radius") || "1";
  const initialOmniValue = currentPostcode || currentSearch;

  const [omniValue, setOmniValue] = useState(initialOmniValue);

  const currentLA = searchParams.get("local_authority") || "";
  const currentType = searchParams.get("school_type") || "";
  const currentPhase = searchParams.get("phase") || "";
  const currentGender = searchParams.get("gender") || "";
  const currentAdmissionsPolicy = searchParams.get("admissions_policy") || "";
  const currentHasSixthForm = searchParams.get("has_sixth_form") || "";

  // Count active dropdown filters (not search/postcode, not phase since it's always visible)
  const activeDropdownFilters = [
    currentLA,
    currentType,
    currentGender,
    currentAdmissionsPolicy,
    currentHasSixthForm,
  ].filter(Boolean);
  const hasActiveDropdownFilters = activeDropdownFilters.length > 0;
  const [filtersOpen, setFiltersOpen] = useState(hasActiveDropdownFilters);

  // Auto-open if filters become active (e.g. URL change)
  useEffect(() => {
    if (hasActiveDropdownFilters) setFiltersOpen(true);
  }, [hasActiveDropdownFilters]);

  useEffect(() => {
    const handleKeyDown = (e: KeyboardEvent) => {
      if (
        (e.key === "/" || (e.key === "k" && (e.ctrlKey || e.metaKey))) &&
        document.activeElement?.tagName !== "INPUT" &&
        document.activeElement?.tagName !== "TEXTAREA" &&
        document.activeElement?.tagName !== "SELECT"
      ) {
        e.preventDefault();
        inputRef.current?.focus();
      }
    };
    document.addEventListener("keydown", handleKeyDown);
    return () => document.removeEventListener("keydown", handleKeyDown);
  }, []);

  const updateURL = useCallback(
    (updates: Record<string, string>) => {
      const params = new URLSearchParams(searchParams);

      Object.entries(updates).forEach(([key, value]) => {
        if (value && value !== "") {
          params.set(key, value);
        } else {
          params.delete(key);
        }
      });

      params.delete("page");

      startTransition(() => {
        router.push(`${pathname}?${params.toString()}`);
      });
    },
    [searchParams, pathname, router],
  );

  const handleSearchSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    if (!omniValue.trim()) {
      updateURL({ search: "", postcode: "", radius: "" });
      return;
    }

    const isPostcode = isValidPostcode(omniValue);
    const cleaned = omniValue.trim();

    // Build a comma-separated active-filter list so a single search event
    // captures the whole intent (vs firing N events as filters are picked).
    const filters_active = [
      currentPhase && `phase=${currentPhase}`,
      currentLA && `la=${currentLA}`,
      currentType && `type=${currentType}`,
      currentGender && `gender=${currentGender}`,
      currentAdmissionsPolicy && `admissions=${currentAdmissionsPolicy}`,
      currentHasSixthForm && `sixth_form=${currentHasSixthForm}`,
    ].filter(Boolean).join(',');

    track('search_submitted', {
      query: isPostcode ? cleaned.toUpperCase() : cleaned.toLowerCase(),
      via: 'input',
      has_postcode: isPostcode,
      filters_active,
      filters_count: filters_active ? filters_active.split(',').length : 0,
    });

    if (isPostcode) {
      updateURL({
        postcode: cleaned.toUpperCase(),
        radius: currentRadius || "1",
        search: "",
      });
    } else {
      updateURL({ search: cleaned, postcode: "", radius: "" });
    }
  };

  const handleFilterChange = (key: string, value: string) => {
    updateURL({ [key]: value });
  };

  const handleClearFilters = () => {
    setOmniValue("");
    startTransition(() => {
      router.push(pathname);
    });
  };

  const hasActiveFilters =
    currentSearch ||
    currentLA ||
    currentType ||
    currentPhase ||
    currentPostcode ||
    currentGender ||
    currentAdmissionsPolicy ||
    currentHasSixthForm;

  // Use result-scoped filter values when available, fall back to global
  const laOptions =
    resultFilters?.local_authorities ?? filters.local_authorities;
  const typeOptions = resultFilters?.school_types ?? filters.school_types;
  const phaseOptions = resultFilters?.phases ?? filters.phases ?? [];
  const genderOptions = resultFilters?.genders ?? filters.genders ?? [];
  const admissionsPolicyOptions =
    resultFilters?.admissions_policies ?? filters.admissions_policies ?? [];

  const isSecondaryMode =
    currentPhase === "secondary" || genderOptions.length > 0;

  // A select that is narrowing the results carries a sage tint; the class is
  // only ever additive, so the control's behaviour is untouched.
  const activeIf = (value: string) => (value ? ` ${styles.selectActive}` : "");

  return (
    <div
      className={`${styles.filterBar} ${isPending ? styles.isLoading : ""} ${isHero ? styles.heroMode : ""}`}
    >
      <form onSubmit={handleSearchSubmit} className={styles.searchSection}>
        <div className={styles.omniBoxContainer}>
          {isHero && (
            <span className={styles.omniIcon} aria-hidden="true">
              <svg
                width="18"
                height="18"
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                strokeWidth="2"
                strokeLinecap="round"
                strokeLinejoin="round"
              >
                <path d="M12 21s7-5.6 7-11a7 7 0 1 0-14 0c0 5.4 7 11 7 11Z" />
                <circle cx="12" cy="10" r="2.6" />
              </svg>
            </span>
          )}
          <input
            ref={inputRef}
            type="search"
            value={omniValue}
            onChange={(e) => setOmniValue(e.target.value)}
            placeholder="School name or postcode"
            className={styles.omniInput}
          />
          <button
            type="submit"
            className={`btn btn-action ${styles.searchButton}`}
            disabled={isPending}
          >
            {isPending ? <div className={styles.spinner}></div> : isHero ? "Search schools" : "Search"}
          </button>
        </div>
        {isHero && (
          <>
            <p className={styles.searchHint}>
              Search by <strong>school name</strong> — or use your{" "}
              <strong>postcode</strong> for the nearest schools.
            </p>
            {onNearMe && (
              <div className={styles.nearMeRow}>
                <button
                  type="button"
                  className={styles.nearMeBtn}
                  onClick={onNearMe}
                  disabled={geoState === "requesting"}
                >
                  {geoState === "requesting" ? (
                    <>
                      <span className={styles.nearMeSpinner} aria-hidden="true" />
                      Locating you…
                    </>
                  ) : (
                    <>
                      <svg
                        width="15"
                        height="15"
                        viewBox="0 0 24 24"
                        fill="none"
                        stroke="currentColor"
                        strokeWidth="2.5"
                        aria-hidden="true"
                      >
                        <path d="M12 2a7 7 0 0 1 7 7c0 5.25-7 13-7 13S5 14.25 5 9a7 7 0 0 1 7-7z" />
                        <circle cx="12" cy="9" r="2.5" />
                      </svg>
                      Use my location
                    </>
                  )}
                </button>
                {geoError && (
                  <p className={styles.geoError} role="alert">
                    {geoError}
                  </p>
                )}
              </div>
            )}
          </>
        )}
      </form>

      {!isHero && (
        <>
          <div className={styles.controlsRow}>
            {currentPostcode && (
              <div className={styles.radiusControl}>
                <label className={styles.radiusLabel}>Within:</label>
                <SelectShell>
                  <select
                    value={currentRadius}
                    onChange={(e) => updateURL({ radius: e.target.value })}
                    className={styles.controlSelect}
                    disabled={isPending}
                  >
                    <option value="0.5">0.5 miles</option>
                    <option value="1">1 mile</option>
                    <option value="3">3 miles</option>
                    <option value="5">5 miles</option>
                  </select>
                </SelectShell>
              </div>
            )}

            {phaseOptions.length > 0 && (
              <SelectShell>
                <select
                  value={currentPhase}
                  onChange={(e) => handleFilterChange("phase", e.target.value)}
                  className={`${styles.controlSelect}${activeIf(currentPhase)}`}
                  disabled={isPending}
                >
                  <option value="">All Phases</option>
                  {phaseOptions.map((p) => (
                    <option key={p} value={p.toLowerCase()}>
                      {p}
                    </option>
                  ))}
                </select>
              </SelectShell>
            )}

            <button
              type="button"
              className={`${styles.advancedToggle}${hasActiveDropdownFilters ? ` ${styles.advancedToggleActive}` : ''}`}
              onClick={() => setFiltersOpen((v) => !v)}
              aria-expanded={filtersOpen}
            >
              {hasActiveDropdownFilters ? 'Filters' : 'Advanced'}
              {hasActiveDropdownFilters
                ? ` (${activeDropdownFilters.length})`
                : ""}
              <span
                className={filtersOpen ? styles.chevronUp : styles.chevronDown}
              />
            </button>

            {hasActiveFilters && (
              <button
                onClick={handleClearFilters}
                className={`btn btn-tertiary ${styles.clearButton}`}
                type="button"
                disabled={isPending}
              >
                Clear
              </button>
            )}
          </div>

          {filtersOpen && (
            <div className={styles.filters}>
              <SelectShell wide>
                <select
                  value={currentLA}
                  onChange={(e) =>
                    handleFilterChange("local_authority", e.target.value)
                  }
                  className={`${styles.filterSelect}${activeIf(currentLA)}`}
                  disabled={isPending}
                >
                  <option value="">All Local Authorities</option>
                  {laOptions.map((la) => (
                    <option key={la} value={la}>
                      {la}
                    </option>
                  ))}
                </select>
              </SelectShell>

              <SelectShell wide>
                <select
                  value={currentType}
                  onChange={(e) =>
                    handleFilterChange("school_type", e.target.value)
                  }
                  className={`${styles.filterSelect}${activeIf(currentType)}`}
                  disabled={isPending}
                >
                  <option value="">All School Types</option>
                  {typeOptions.map((type) => (
                    <option key={type} value={type}>
                      {type}
                    </option>
                  ))}
                </select>
              </SelectShell>

              {isSecondaryMode && (
                <>
                  {genderOptions.length > 0 && (
                    <SelectShell wide>
                      <select
                        value={currentGender}
                        onChange={(e) =>
                          handleFilterChange("gender", e.target.value)
                        }
                        className={`${styles.filterSelect}${activeIf(currentGender)}`}
                        disabled={isPending}
                      >
                        <option value="">Boys, Girls &amp; Mixed</option>
                        {genderOptions.map((g) => (
                          <option key={g} value={g.toLowerCase()}>
                            {g}
                          </option>
                        ))}
                      </select>
                    </SelectShell>
                  )}

                  <SelectShell wide>
                    <select
                      value={currentHasSixthForm}
                      onChange={(e) =>
                        handleFilterChange("has_sixth_form", e.target.value)
                      }
                      className={`${styles.filterSelect}${activeIf(currentHasSixthForm)}`}
                      disabled={isPending}
                    >
                      <option value="">With or without sixth form</option>
                      <option value="yes">With sixth form</option>
                      <option value="no">Without sixth form</option>
                    </select>
                  </SelectShell>

                  {admissionsPolicyOptions.length > 0 && (
                    <SelectShell wide>
                      <select
                        value={currentAdmissionsPolicy}
                        onChange={(e) =>
                          handleFilterChange("admissions_policy", e.target.value)
                        }
                        className={`${styles.filterSelect}${activeIf(currentAdmissionsPolicy)}`}
                        disabled={isPending}
                      >
                        <option value="">All admissions types</option>
                        {admissionsPolicyOptions.map((p) => (
                          <option key={p} value={p.toLowerCase()}>
                            {p}
                          </option>
                        ))}
                      </select>
                    </SelectShell>
                  )}
                </>
              )}
            </div>
          )}
        </>
      )}
    </div>
  );
}
