import React, { useEffect, useMemo, useRef, useState } from "react";
import { useTranslation } from "react-i18next";
import { recoSearch } from "../../services/recoSearch";
import "../../styles/smartSearchBar.css";
import { trackEvent } from "../../utils/analytics";

function defaultZoomForKind(kind) {
  const k = (kind || "").toLowerCase();

  // Specific types from suggestions endpoint
  if (k === "post") return 16;           // Close zoom for posts
  if (k === "profile") return 14;        // Medium zoom for profiles
  if (k === "city") return 11;           // City-level zoom
  if (k === "region") return 5;          // Wide zoom for regions/provinces
  if (k === "place" || k === "poi") return 13;  // Places zoom

  // Legacy/fallback
  if (k.includes("post")) return 15;
  if (k.includes("city")) return 11;
  if (k.includes("region") || k.includes("area") || k.includes("province") || k.includes("state")) return 5;
  if (k.includes("place")) return 13;

  return 12;  // Default
}

function IconPin(props) {
  return (
    <svg viewBox="0 0 24 24" width="18" height="18" aria-hidden="true" {...props}>
      <path
        d="M12 22s7-6.1 7-13a7 7 0 1 0-14 0c0 6.9 7 13 7 13zm0-9.5a3.5 3.5 0 1 1 0-7 3.5 3.5 0 0 1 0 7z"
        fill="currentColor"
      />
    </svg>
  );
}

function IconPlus(props) {
  return (
    <svg viewBox="0 0 24 24" width="18" height="18" aria-hidden="true" {...props}>
      <path
        d="M12 5v14m-7-7h14"
        fill="none"
        stroke="currentColor"
        strokeWidth="2.5"
        strokeLinecap="round"
      />
    </svg>
  );
}

function truncateText(value, maxLen) {
  const s = (value || "").toString();
  if (!maxLen || s.length <= maxLen) return s;
  return s.slice(0, Math.max(0, maxLen - 1)) + "…";
}

/**
 * Props:
 * - placeholder
 * - onPick(item, { zoom, reason })  // call when user selects suggestion
 * - onSearch(query)                 // call when user presses Enter to filter/search
 * - onMySpot()                      // keep same function (center on user)
 * - onPlaceTourWire()               // keep same function (place/tour/wire)
 */
export default function SmartSearchBar({
  onPick,
  onSearch,
  onMySpot,
  onPlaceTourWire,
}) {
  const { t } = useTranslation();
  const [q, setQ] = useState("");
  const [open, setOpen] = useState(false);
  const [loading, setLoading] = useState(false);
  const [items, setItems] = useState([]);
  const [active, setActive] = useState(-1);
  const [err, setErr] = useState("");
  const [hasSearched, setHasSearched] = useState(false);
  const [focused, setFocused] = useState(false);

  const abortRef = useRef(null);
  const skipSearchRef = useRef(false);
  const boxRef = useRef(null);
  const inputRef = useRef(null);
  const searchCacheRef = useRef(new Map()); // key -> { value, expiresAt }
  const latestQueryRef = useRef("");
  const emptySuggestionsFetchedRef = useRef(false);

  // Cache helpers with TTL and case-insensitive keys
  const cacheKey = (q) => (q || "").toLowerCase().trim();
  const cacheGet = (q) => {
    const key = cacheKey(q);
    const entry = searchCacheRef.current.get(key);
    if (!entry) return null;
    if (entry.expiresAt <= Date.now()) {
      searchCacheRef.current.delete(key);
      return null;
    }
    return entry.value;
  };
  const cacheSet = (q, value, ttlMs = 30000) => {
    const key = cacheKey(q);
    // Don't cache empty results - always re-fetch
    if (!value || value.length === 0) return;
    searchCacheRef.current.set(key, { value, expiresAt: Date.now() + ttlMs });
  };

  useEffect(() => {
    function onDocDown(e) {
      if (!boxRef.current) return;
      if (!boxRef.current.contains(e.target)) setOpen(false);
    }
    document.addEventListener("mousedown", onDocDown);
    return () => document.removeEventListener("mousedown", onDocDown);
  }, []);

  // Fonction pour déclencher une recherche
  const triggerSearch = async (searchQuery) => {
    if (abortRef.current) abortRef.current.abort();

    const cached = cacheGet(searchQuery);
    if (cached) {
      setItems(cached);
      setActive(cached.length ? 0 : -1);
      setOpen(true);
      setHasSearched(true);
      setLoading(false);
      return;
    }

    const ctrl = new AbortController();
    abortRef.current = ctrl;
    setLoading(true);
    setErr("");
    setOpen(true);
    latestQueryRef.current = searchQuery;

    try {
      const res = await recoSearch(searchQuery, { signal: ctrl.signal, limit: 12 });
      if (latestQueryRef.current !== searchQuery) return;
      setItems(res);
      setActive(res.length ? 0 : -1);
      setHasSearched(true);
      cacheSet(searchQuery, res); // Won't cache empty results
    } catch (e) {
      if (ctrl.signal.aborted) return;
      setErr((e && e.message) ? e.message : "Search error");
      setItems([]);
      setOpen(true);
    } finally {
      if (!ctrl.signal.aborted) setLoading(false);
    }
  };

  useEffect(() => {
    const query = q.trim();

    if (skipSearchRef.current) {
      skipSearchRef.current = false;
      return;
    }

    if (query) setOpen(true);

    if (abortRef.current) abortRef.current.abort();

    if (!query) {
      setItems([]);
      setOpen(false);
      setHasSearched(false);
      return;
    }

    const t = setTimeout(() => {
      triggerSearch(query);
    }, 200); // Debounce 200ms (faster UX)

    return () => {
      clearTimeout(t);
      if (abortRef.current) abortRef.current.abort();
    };
  }, [q]);

  const showList = (open || focused) && (items.length > 0 || loading || err || q.trim());
  const clearOnFocusRef = useRef(false);

  const pick = (it, reason = "click") => {
    if (!it) return;
    const zoom = defaultZoomForKind(it.kind);
    skipSearchRef.current = true;
    setOpen(false);
    clearOnFocusRef.current = true;

    trackEvent("search_pick", {
      kind: it.kind || "",
      reason,
      query_len: (q || "").length,
      title_len: (it.title || "").length,
    });
    onPick && onPick(it, { zoom, reason });
    if (inputRef.current) {
      try { inputRef.current.blur(); } catch {}
    }
  };

  const onKeyDown = (e) => {
    if (!showList && (e.key === "ArrowDown" || e.key === "Enter")) setOpen(true);

    if (e.key === "ArrowDown") {
      e.preventDefault();
      setActive((i) => Math.min(i + 1, items.length - 1));
    } else if (e.key === "ArrowUp") {
      e.preventDefault();
      setActive((i) => Math.max(i - 1, 0));
    } else if (e.key === "Enter") {
      e.preventDefault();
      if (q.trim()) {
        // Always filter on Enter; do not auto-pick dropdown items.
        skipSearchRef.current = true;
        setOpen(false);
        trackEvent("search_submit", { query_len: q.trim().length });
        onSearch && onSearch(q.trim());
        if (inputRef.current) {
          try { inputRef.current.blur(); } catch {}
        }
      }
    } else if (e.key === "Escape") {
      setOpen(false);
    }
  };

  const rightTitle = useMemo(() => {
    // visuel flexible, même fonction: tu peux renommer plus tard
    return "Place / Tour / Wire";
  }, []);

  const handleClear = () => {
    setQ("");
    setItems([]);
    setOpen(false);
    trackEvent("search_clear");
    onSearch && onSearch(""); // Clear filters
  };

  return (
    <div className="sw-search" ref={boxRef}>
      <div className="sw-search__bar">
        <input
          ref={inputRef}
          className="sw-search__input"
          value={q}
          onChange={(e) => {
            const newValue = e.target.value;
            setQ(newValue);
            // Si on efface tout le texte, clear les filtres
            if (!newValue.trim() && q.trim()) {
              onSearch && onSearch("");
            }
          }}
          onFocus={() => {
            setFocused(true);
            if (clearOnFocusRef.current) {
              clearOnFocusRef.current = false;
              setQ("");
              setItems([]);
              setOpen(true);
              onSearch && onSearch("");
              return;
            }
            if (!q.trim() && !emptySuggestionsFetchedRef.current) {
              emptySuggestionsFetchedRef.current = true;
              triggerSearch("");
            }
            setOpen(true);
          }}
          onBlur={() => {
            setTimeout(() => setFocused(false), 120);
          }}
          onKeyDown={onKeyDown}
          placeholder={t('map.searchPlaceholder')}
          aria-label={t('common.search')}
        />

        {q && (
          <button
            type="button"
            className="sw-search__clearBtn"
            title={t('map.clearSearch')}
            onClick={handleClear}
            aria-label={t('map.clearSearch')}
          >
            <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" strokeWidth="2">
              <path d="M18 6L6 18M6 6l12 12" />
            </svg>
          </button>
        )}

        <div className="sw-search__icons" aria-label="Search actions">
          <button
            type="button"
            className="sw-search__iconBtn"
            title={t('map.mySpot')}
            onClick={() => {
              trackEvent("search_my_spot");
              onMySpot && onMySpot();
            }}
          >
            <IconPin />
          </button>
        </div>
      </div>

      {showList && (
        <div className="sw-search__dropdown">
          {loading && <div className="sw-search__row sw-search__muted">{t('map.searching')}</div>}
          {err && <div className="sw-search__row sw-search__error">{err}</div>}

          {!err && items.map((it, idx) => (
            <button
              type="button"
              key={it.id}
              className={"sw-search__row sw-search__item" + (idx === active ? " is-active" : "")}
              onMouseEnter={() => setActive(idx)}
              onMouseDown={(e) => {
                e.preventDefault();
                pick(it, "click");
              }}
              onClick={(e) => {
                e.preventDefault();
              }}
            >
              <div className="sw-search__title">{truncateText(it.title || t('common.untitled'), 140)}</div>
              <div className="sw-search__sub">
                {truncateText((it.kind ? it.kind : "result") + (it.subtitle ? " • " + it.subtitle : ""), 120)}
              </div>
              {Array.isArray(it.tags) && it.tags.length > 0 && (
                <div className="sw-search__tags">
                  {it.tags.slice(0, 4).map((tag) => (
                    <span key={tag} className="sw-search__tag">#{tag}</span>
                  ))}
                </div>
              )}
            </button>
          ))}

          {!loading && !err && items.length === 0 && (
            <div className="sw-search__row sw-search__muted">{t('map.noResults')}</div>
          )}
        </div>
      )}
    </div>
  );
}
