"use client";

import { useEffect, useRef, useState } from "react";

export type Suggestion = { id: string; name: string; slug: string };
type BlockedInfo = { name: string; note: string | null } | null;

function useDebounced<T>(value: T, delayMs: number) {
  const [debounced, setDebounced] = useState(value);
  useEffect(() => {
    const timer = setTimeout(() => setDebounced(value), delayMs);
    return () => clearTimeout(timer);
  }, [value, delayMs]);
  return debounced;
}

export function BrandBlendAutocomplete({
  blendFieldName = "blendId",
  initialBrand = null,
  initialBlend = null,
}: {
  blendFieldName?: string;
  initialBrand?: Suggestion | null;
  initialBlend?: Suggestion | null;
}) {
  const [brandQuery, setBrandQuery] = useState("");
  const [brandResults, setBrandResults] = useState<Suggestion[]>([]);
  const [brandBlocked, setBrandBlocked] = useState<BlockedInfo>(null);
  const [selectedBrand, setSelectedBrand] = useState<Suggestion | null>(
    initialBrand,
  );

  const [blendQuery, setBlendQuery] = useState("");
  const [blendResults, setBlendResults] = useState<Suggestion[]>([]);
  const [blendBlocked, setBlendBlocked] = useState<BlockedInfo>(null);
  const [selectedBlend, setSelectedBlend] = useState<Suggestion | null>(
    initialBlend,
  );

  const debouncedBrandQuery = useDebounced(brandQuery, 250);
  const debouncedBlendQuery = useDebounced(blendQuery, 250);
  const requestId = useRef(0);

  useEffect(() => {
    if (selectedBrand || !debouncedBrandQuery) {
      return;
    }
    const currentRequest = ++requestId.current;
    fetch(`/api/brands/search?q=${encodeURIComponent(debouncedBrandQuery)}`)
      .then((res) => res.json())
      .then((data) => {
        if (currentRequest !== requestId.current) return;
        setBrandResults(data.results ?? []);
        setBrandBlocked(data.blocked ?? null);
      });
  }, [debouncedBrandQuery, selectedBrand]);

  useEffect(() => {
    if (!selectedBrand || selectedBlend || !debouncedBlendQuery) {
      return;
    }
    fetch(
      `/api/blends/search?brand_id=${selectedBrand.id}&q=${encodeURIComponent(debouncedBlendQuery)}`,
    )
      .then((res) => res.json())
      .then((data) => {
        setBlendResults(data.results ?? []);
        setBlendBlocked(data.blocked ?? null);
      });
  }, [debouncedBlendQuery, selectedBrand, selectedBlend]);

  return (
    <div className="flex flex-col gap-6">
      <input
        type="hidden"
        name={blendFieldName}
        value={selectedBlend?.id ?? ""}
      />

      <div className="relative">
        <label className="flex flex-col gap-1">
          <span className="text-sm font-medium text-charcoal">Brand</span>
          <input
            type="text"
            value={selectedBrand ? selectedBrand.name : brandQuery}
            onChange={(e) => {
              setSelectedBrand(null);
              setSelectedBlend(null);
              setBrandQuery(e.target.value);
            }}
            placeholder="Start typing a brand name..."
            className="rounded border border-charcoal/20 bg-warm-white px-4 py-2 text-charcoal"
          />
        </label>

        {!selectedBrand && brandBlocked && (
          <p className="mt-2 rounded bg-terracotta/10 px-4 py-2 text-sm text-terracotta">
            &ldquo;{brandBlocked.name}&rdquo; is not allowed.
            {brandBlocked.note ? ` ${brandBlocked.note}` : ""}
          </p>
        )}

        {!selectedBrand && brandQuery && brandResults.length > 0 && (
          <ul className="absolute z-10 mt-1 w-full rounded border border-charcoal/20 bg-warm-white shadow-lg">
            {brandResults.map((brand) => (
              <li key={brand.id}>
                <button
                  type="button"
                  onClick={() => {
                    setSelectedBrand(brand);
                    setBrandQuery("");
                    setBrandResults([]);
                  }}
                  className="w-full px-4 py-2 text-left hover:bg-cream"
                >
                  {brand.name}
                </button>
              </li>
            ))}
          </ul>
        )}
      </div>

      <div className="relative">
        <label className="flex flex-col gap-1">
          <span className="text-sm font-medium text-charcoal">Blend</span>
          <input
            type="text"
            value={selectedBlend ? selectedBlend.name : blendQuery}
            onChange={(e) => {
              setSelectedBlend(null);
              setBlendQuery(e.target.value);
            }}
            disabled={!selectedBrand}
            placeholder={
              selectedBrand
                ? "Start typing a blend name..."
                : "Select a brand first"
            }
            className="rounded border border-charcoal/20 bg-warm-white px-4 py-2 text-charcoal disabled:opacity-50"
          />
        </label>

        {!selectedBlend && blendBlocked && (
          <p className="mt-2 rounded bg-terracotta/10 px-4 py-2 text-sm text-terracotta">
            &ldquo;{blendBlocked.name}&rdquo; is not allowed.
            {blendBlocked.note ? ` ${blendBlocked.note}` : ""}
          </p>
        )}

        {!selectedBlend && blendQuery && blendResults.length > 0 && (
          <ul className="absolute z-10 mt-1 w-full rounded border border-charcoal/20 bg-warm-white shadow-lg">
            {blendResults.map((blend) => (
              <li key={blend.id}>
                <button
                  type="button"
                  onClick={() => {
                    setSelectedBlend(blend);
                    setBlendQuery("");
                    setBlendResults([]);
                  }}
                  className="w-full px-4 py-2 text-left hover:bg-cream"
                >
                  {blend.name}
                </button>
              </li>
            ))}
          </ul>
        )}
      </div>

      {selectedBrand && selectedBlend && (
        <p className="text-charcoal">
          Selected: <strong>{selectedBrand.name}</strong> -{" "}
          {selectedBlend.name}
        </p>
      )}
    </div>
  );
}
