"use client";

/**
 * AddressInput — combobox с автокомплитом адресов в ЕКБ.
 * Стиль: `.ac-list .ac-item .ac-main .ac-sub` из tradein.html mockup.
 *
 * Особенности:
 * - 200ms debounce
 * - Открывается при focus и при наборе
 * - Закрывается по click outside + Esc
 * - Выбор по mouseDown (предотвращает blur)
 * - ↑↓ навигация, Enter / Tab выбор
 * - Поддерживает typo-tolerance через backend (Цвилинга → Цвиллинга)
 */
import { useEffect, useRef, useState } from "react";

import { apiFetch } from "@/lib/api";

interface SuggestItem {
  label: string;
  full_address: string;
  lat: number;
  lon: number;
  kind: string;
  // ФИАС-идентификатор дома (заполнен только для house-level кандидатов
  // DaData-тира; иначе null/absent). Пробрасывается наверх через onPickFias.
  fias_id?: string | null;
}

interface SuggestResponse {
  items: SuggestItem[];
}

// Pre-filled тестовые адреса — клик подставляет в поле и заодно дёргает suggest.
// Все эти адреса дают «medium» или «high» confidence на 2-room 50м² (хорошее покрытие).
const PRESET_ADDRESSES: { label: string; full: string; kind: string }[] = [
  { label: "ул. Малышева, 84 · Парковый", full: "Екатеринбург, ул. Малышева, 84", kind: "house" },
  { label: "ул. Куйбышева, 48 · Парковый", full: "Екатеринбург, ул. Куйбышева, 48", kind: "house" },
  { label: "ул. 8 Марта, 50 · Ленинский р-н", full: "Екатеринбург, ул. 8 Марта, 50", kind: "house" },
  { label: "ул. Цвиллинга, 58 · Парковый", full: "Екатеринбург, улица Цвиллинга, 58", kind: "house" },
  { label: "ул. Белинского, 200 · ЮЗ", full: "Екатеринбург, ул. Белинского, 200", kind: "house" },
  { label: "ул. Куйбышева, 30 · центр", full: "Екатеринбург, ул. Куйбышева, 30", kind: "house" },
];

interface Props {
  value: string;
  onChange: (val: string) => void;
  onPickCoords?: (coords: { lat: number; lon: number } | null) => void;
  // ФИАС-ключ выбранного дома. Зеркалит поведение onPickCoords: значение при
  // выборе house-level подсказки, null при ручной правке текста.
  onPickFias?: (fiasId: string | null) => void;
  placeholder?: string;
  inputId?: string;
}

const KIND_BADGE: Record<string, { tag: string; label: string }> = {
  house: { tag: "ДОМ", label: "house" },
  street: { tag: "УЛ", label: "street" },
  locality: { tag: "Р-Н", label: "locality" },
};

function AreaSubtitle({ item }: { item: SuggestItem }) {
  const kindBadge = KIND_BADGE[item.kind] ?? { tag: item.kind.toUpperCase(), label: item.kind };
  return (
    <span className="ac-sub" style={{ display: "flex", gap: 6, alignItems: "center" }}>
      <span
        style={{
          padding: "1px 5px",
          background: "var(--surface-3)",
          color: "var(--muted)",
          borderRadius: 3,
          fontSize: 9,
          fontWeight: 600,
          letterSpacing: "0.05em",
        }}
      >
        {kindBadge.tag}
      </span>
    </span>
  );
}

function presetsToItems(): SuggestItem[] {
  return PRESET_ADDRESSES.map((p) => ({
    label: p.label,
    full_address: p.full,
    lat: 0,
    lon: 0,
    kind: p.kind,
    fias_id: null,
  }));
}

export function AddressInput({ value, onChange, onPickCoords, onPickFias, placeholder, inputId = "addr" }: Props) {
  const [open, setOpen] = useState(false);
  const [items, setItems] = useState<SuggestItem[]>([]);
  const [loading, setLoading] = useState(false);
  const [highlight, setHighlight] = useState(0);
  const [showPresets, setShowPresets] = useState(false);
  const containerRef = useRef<HTMLDivElement | null>(null);
  const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);
  const lastPickedRef = useRef<string>("");

  // Debounced fetch на каждое изменение value
  useEffect(() => {
    const q = value.trim();
    if (q.length < 2) {
      setItems([]);
      setOpen(false);
      return;
    }
    setShowPresets(false);
    // Если value совпадает с последним выбранным — не делаем запрос
    if (q === lastPickedRef.current) return;

    if (debounceRef.current) clearTimeout(debounceRef.current);
    debounceRef.current = setTimeout(async () => {
      setLoading(true);
      try {
        const r = await apiFetch<SuggestResponse>(
          `/api/v1/geocode/suggest?q=${encodeURIComponent(q)}&limit=8`,
        );
        setItems(r.items);
        setOpen(r.items.length > 0);
        setHighlight(0);
      } catch {
        setItems([]);
        setOpen(false);
      } finally {
        setLoading(false);
      }
    }, 200);

    return () => {
      if (debounceRef.current) clearTimeout(debounceRef.current);
    };
  }, [value]);

  // Click outside → close
  useEffect(() => {
    function onClick(e: MouseEvent) {
      if (containerRef.current && !containerRef.current.contains(e.target as Node)) {
        setOpen(false);
        setShowPresets(false);
      }
    }
    document.addEventListener("mousedown", onClick);
    return () => document.removeEventListener("mousedown", onClick);
  }, []);

  function pick(item: SuggestItem) {
    lastPickedRef.current = item.full_address;
    onChange(item.full_address);
    const hasCoords =
      Number.isFinite(item.lat) &&
      Number.isFinite(item.lon) &&
      item.lat !== 0 &&
      item.lon !== 0;
    onPickCoords?.(hasCoords ? { lat: item.lat, lon: item.lon } : null);
    onPickFias?.(item.fias_id ?? null);
    setOpen(false);
    setShowPresets(false);
    setItems([]);
  }

  // Активный список для UI (suggest result ИЛИ presets)
  const activeItems: SuggestItem[] = showPresets ? presetsToItems() : items;
  const dropdownOpen = (open && items.length > 0) || (showPresets && activeItems.length > 0);

  function onKeyDown(e: React.KeyboardEvent<HTMLInputElement>) {
    if (!dropdownOpen) {
      if (e.key === "ArrowDown") {
        // Открываем dropdown — либо результаты suggest, либо presets
        if (items.length > 0) setOpen(true);
        else if (value.trim().length < 2) setShowPresets(true);
        e.preventDefault();
      }
      return;
    }
    if (e.key === "ArrowDown") {
      e.preventDefault();
      setHighlight((h) => Math.min(activeItems.length - 1, h + 1));
    } else if (e.key === "ArrowUp") {
      e.preventDefault();
      setHighlight((h) => Math.max(0, h - 1));
    } else if (e.key === "Enter" || e.key === "Tab") {
      e.preventDefault();
      pick(activeItems[highlight]);
    } else if (e.key === "Escape") {
      setOpen(false);
      setShowPresets(false);
    }
  }

  return (
    <div ref={containerRef} style={{ position: "relative", width: "100%" }}>
      <input
        id={inputId}
        type="text"
        className="control"
        placeholder={placeholder}
        value={value}
        autoComplete="off"
        onChange={(e) => {
          onChange(e.target.value);
          lastPickedRef.current = ""; // юзер начал редактировать — снимаем guard
          onPickCoords?.(null); // ручное редактирование сбрасывает ранее выбранные coords
          onPickFias?.(null); // ...и ранее выбранный ФИАС (иначе stale перебьёт новый адрес)
          setShowPresets(false);
        }}
        onFocus={() => {
          // Если есть свежий suggest result — открываем его
          if (items.length > 0) {
            setOpen(true);
            return;
          }
          // Если поле пустое — показываем тестовые адреса
          if (value.trim().length < 2) {
            setShowPresets(true);
            setHighlight(0);
          }
        }}
        onKeyDown={onKeyDown}
        minLength={3}
        maxLength={500}
        required
      />
      {loading && (
        <span
          aria-hidden="true"
          style={{
            position: "absolute",
            right: 10,
            top: "50%",
            transform: "translateY(-50%)",
            fontSize: 10,
            color: "var(--muted-2)",
          }}
        >
          <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" style={{ animation: "ti-spin 1s linear infinite" }}>
            <path d="M21 12a9 9 0 1 1-6.219-8.56" />
          </svg>
        </span>
      )}
      <ul className={`ac-list ${dropdownOpen ? "is-open" : ""}`} role="listbox">
        {showPresets && (
          <li
            style={{
              padding: "6px 10px",
              fontSize: 10,
              color: "var(--muted-2)",
              fontWeight: 600,
              letterSpacing: "0.08em",
              textTransform: "uppercase",
              borderBottom: "1px solid var(--border)",
              cursor: "default",
            }}
          >
            Подсказки · нажмите для подстановки
          </li>
        )}
        {activeItems.map((it, i) => (
          <li
            key={`${it.full_address}-${i}`}
            className={`ac-item ${i === highlight ? "is-focus" : ""}`}
            role="option"
            aria-selected={i === highlight}
            onMouseEnter={() => setHighlight(i)}
            onMouseDown={(e) => {
              // mousedown (не click) — иначе input blur'ится до того как обработаем
              e.preventDefault();
              pick(it);
            }}
          >
            <span className="ac-main">{it.label}</span>
            <AreaSubtitle item={it} />
          </li>
        ))}
      </ul>
    </div>
  );
}
