import { useRef, useEffect, useState } from "react";
import { Plus, X, Upload, Loader2, Link, ImageIcon, Calendar, AlertCircle, MapPin } from "lucide-react";
import type { RichListItem, VictoryItem } from "@/types/content";

interface InputFieldProps {
  label: string;
  value: string;
  onChange: (value: string) => void;
  placeholder?: string;
  type?: "text" | "url" | "tel";
}

export function InputField({
  label,
  value,
  onChange,
  placeholder,
  type = "text",
}: InputFieldProps) {
  return (
    <div>
      <label className="block text-sm text-neutral-400 mb-1.5">{label}</label>
      <input
        type={type}
        value={value}
        onChange={(e) => onChange(e.target.value)}
        placeholder={placeholder}
        className="w-full rounded-lg border border-white/10 bg-neutral-800 px-4 py-2.5 text-white placeholder-neutral-500 outline-none focus:border-gold transition-colors"
      />
    </div>
  );
}

interface TextareaFieldProps {
  label: string;
  value: string;
  onChange: (value: string) => void;
  placeholder?: string;
  rows?: number;
}

export function TextareaField({
  label,
  value,
  onChange,
  placeholder,
  rows = 3,
}: TextareaFieldProps) {
  const ref = useRef<HTMLTextAreaElement>(null);

  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    el.style.height = "auto";
    el.style.height = el.scrollHeight + "px";
  }, [value]);

  useEffect(() => {
    function onResize() {
      const el = ref.current;
      if (!el) return;
      el.style.height = "auto";
      el.style.height = el.scrollHeight + "px";
    }
    window.addEventListener("resize", onResize);
    return () => window.removeEventListener("resize", onResize);
  }, []);

  return (
    <div>
      <label className="block text-sm text-neutral-400 mb-1.5">{label}</label>
      <textarea
        ref={ref}
        value={value}
        onChange={(e) => onChange(e.target.value)}
        placeholder={placeholder}
        rows={rows}
        className="w-full rounded-lg border border-white/10 bg-neutral-800 px-4 py-2.5 text-white placeholder-neutral-500 outline-none focus:border-gold transition-colors resize-none overflow-hidden"
      />
    </div>
  );
}

interface SelectFieldProps {
  label: string;
  value: string;
  onChange: (value: string) => void;
  options: { value: string; label: string }[];
  placeholder?: string;
}

export function SelectField({
  label,
  value,
  onChange,
  options,
  placeholder,
}: SelectFieldProps) {
  const [open, setOpen] = useState(false);
  const [search, setSearch] = useState("");
  const containerRef = useRef<HTMLDivElement>(null);
  const inputRef = useRef<HTMLInputElement>(null);

  const selectedLabel = options.find((o) => o.value === value)?.label || "";
  const filtered = search
    ? options.filter((o) => {
        const q = search.toLowerCase();
        return o.label.toLowerCase().split(/\s+/).some((word) => word.startsWith(q));
      })
    : options;

  useEffect(() => {
    if (!open) return;
    function handle(e: MouseEvent) {
      if (containerRef.current && !containerRef.current.contains(e.target as Node)) {
        setOpen(false);
        setSearch("");
      }
    }
    document.addEventListener("mousedown", handle);
    return () => document.removeEventListener("mousedown", handle);
  }, [open]);

  return (
    <div ref={containerRef} className="relative">
      <label className="block text-sm text-neutral-400 mb-1.5">{label}</label>
      <button
        type="button"
        onClick={() => {
          setOpen(!open);
          setSearch("");
          setTimeout(() => inputRef.current?.focus(), 0);
        }}
        className={`w-full rounded-lg border bg-neutral-800 px-4 py-2.5 text-left outline-none transition-colors ${
          open ? "border-gold" : "border-white/10"
        } ${value ? "text-white" : "text-neutral-500"}`}
      >
        {selectedLabel || placeholder || "Выберите..."}
      </button>

      {open && (
        <div className="absolute z-50 mt-1 w-full rounded-lg border border-white/10 bg-neutral-800 shadow-xl overflow-hidden">
          {options.length > 3 && (
            <div className="p-1.5">
              <input
                ref={inputRef}
                type="text"
                value={search}
                onChange={(e) => setSearch(e.target.value)}
                placeholder="Поиск..."
                className="w-full rounded-md border border-white/10 bg-neutral-900 px-3 py-1.5 text-sm text-white outline-none focus:border-gold/50 placeholder:text-neutral-600"
              />
            </div>
          )}
          <div className="max-h-48 overflow-y-auto">
            {filtered.length === 0 && (
              <div className="px-4 py-2 text-sm text-neutral-500">Ничего не найдено</div>
            )}
            {filtered.map((opt) => (
              <button
                key={opt.value}
                type="button"
                onClick={() => {
                  onChange(opt.value);
                  setOpen(false);
                  setSearch("");
                }}
                className={`w-full px-4 py-2 text-left text-sm transition-colors hover:bg-white/5 ${
                  opt.value === value ? "text-gold bg-gold/5" : "text-white"
                }`}
              >
                {opt.label}
              </button>
            ))}
          </div>
        </div>
      )}
    </div>
  );
}

interface TimeRangeFieldProps {
  label: string;
  value: string;
  onChange: (value: string) => void;
  onBlur?: () => void;
}

export function TimeRangeField({ label, value, onChange, onBlur }: TimeRangeFieldProps) {
  const parts = value.split("–");
  const start = parts[0]?.trim() || "";
  const end = parts[1]?.trim() || "";

  function update(s: string, e: string) {
    if (s && e) {
      onChange(`${s}–${e}`);
    } else if (s) {
      onChange(s);
    } else {
      onChange("");
    }
  }

  function handleStartChange(newStart: string) {
    if (newStart && end && newStart >= end) {
      update(newStart, "");
    } else {
      update(newStart, end);
    }
  }

  function handleEndChange(newEnd: string) {
    if (start && newEnd && newEnd <= start) return;
    update(start, newEnd);
  }

  return (
    <div>
      <label className="block text-sm text-neutral-400 mb-1.5">{label}</label>
      <div className="flex items-center gap-2">
        <input
          type="time"
          value={start}
          onChange={(e) => handleStartChange(e.target.value)}
          onBlur={onBlur}
          className="flex-1 rounded-lg border border-white/10 bg-neutral-800 px-3 py-2.5 text-white outline-none focus:border-gold transition-colors"
        />
        <span className="text-neutral-500">–</span>
        <input
          type="time"
          value={end}
          onChange={(e) => handleEndChange(e.target.value)}
          onBlur={onBlur}
          className="flex-1 rounded-lg border border-white/10 bg-neutral-800 px-3 py-2.5 text-white outline-none focus:border-gold transition-colors"
        />
      </div>
    </div>
  );
}

interface ToggleFieldProps {
  label: string;
  checked: boolean;
  onChange: (checked: boolean) => void;
}

export function ToggleField({ label, checked, onChange }: ToggleFieldProps) {
  return (
    <label className="flex items-center gap-2 cursor-pointer">
      <button
        type="button"
        role="switch"
        aria-checked={checked}
        onClick={() => onChange(!checked)}
        className={`relative h-6 w-11 rounded-full transition-colors ${
          checked ? "bg-gold" : "bg-neutral-700"
        }`}
      >
        <span
          className={`absolute top-0.5 left-0.5 h-5 w-5 rounded-full bg-white transition-transform ${
            checked ? "translate-x-5" : ""
          }`}
        />
      </button>
      <span className="text-sm text-neutral-300">{label}</span>
    </label>
  );
}

interface ListFieldProps {
  label: string;
  items: string[];
  onChange: (items: string[]) => void;
  placeholder?: string;
}

export function ListField({ label, items, onChange, placeholder }: ListFieldProps) {
  const [draft, setDraft] = useState("");

  function add() {
    const val = draft.trim();
    if (!val) return;
    onChange([...items, val]);
    setDraft("");
  }

  function remove(index: number) {
    onChange(items.filter((_, i) => i !== index));
  }

  function update(index: number, value: string) {
    onChange(items.map((item, i) => (i === index ? value : item)));
  }

  return (
    <div>
      <label className="block text-sm text-neutral-400 mb-1.5">{label}</label>
      <div className="space-y-2">
        {items.map((item, i) => (
          <div key={i} className="flex items-center gap-2">
            <input
              type="text"
              value={item}
              onChange={(e) => update(i, e.target.value)}
              className="flex-1 rounded-lg border border-white/10 bg-neutral-800 px-4 py-2 text-sm text-white outline-none focus:border-gold transition-colors"
            />
            <button
              type="button"
              onClick={() => remove(i)}
              className="shrink-0 rounded-lg p-2 text-neutral-500 hover:text-red-400 transition-colors"
            >
              <X size={14} />
            </button>
          </div>
        ))}
        <div className="flex items-center gap-2">
          <input
            type="text"
            value={draft}
            onChange={(e) => setDraft(e.target.value)}
            onKeyDown={(e) => { if (e.key === "Enter") { e.preventDefault(); add(); } }}
            placeholder={placeholder || "Добавить..."}
            className="flex-1 rounded-lg border border-dashed border-white/10 bg-neutral-800/50 px-4 py-2 text-sm text-white placeholder-neutral-600 outline-none focus:border-gold/50 transition-colors"
          />
          <button
            type="button"
            onClick={add}
            disabled={!draft.trim()}
            className="shrink-0 rounded-lg p-2 text-neutral-500 hover:text-gold transition-colors disabled:opacity-30"
          >
            <Plus size={14} />
          </button>
        </div>
      </div>
    </div>
  );
}

interface VictoryListFieldProps {
  label: string;
  items: RichListItem[];
  onChange: (items: RichListItem[]) => void;
  placeholder?: string;
  onLinkValidate?: (key: string, error: string | null) => void;
}

export function VictoryListField({ label, items, onChange, placeholder, onLinkValidate }: VictoryListFieldProps) {
  const [draft, setDraft] = useState("");
  const [uploadingIndex, setUploadingIndex] = useState<number | null>(null);

  function add() {
    const val = draft.trim();
    if (!val) return;
    onChange([...items, { text: val }]);
    setDraft("");
  }

  function remove(index: number) {
    onChange(items.filter((_, i) => i !== index));
  }

  function updateText(index: number, text: string) {
    onChange(items.map((item, i) => (i === index ? { ...item, text } : item)));
  }

  function updateLink(index: number, link: string) {
    onChange(items.map((item, i) => (i === index ? { ...item, link: link || undefined } : item)));
  }

  function removeImage(index: number) {
    onChange(items.map((item, i) => (i === index ? { ...item, image: undefined } : item)));
  }

  async function handleUpload(index: number, e: React.ChangeEvent<HTMLInputElement>) {
    const file = e.target.files?.[0];
    if (!file) return;
    setUploadingIndex(index);
    const formData = new FormData();
    formData.append("file", file);
    formData.append("folder", "team");
    try {
      const res = await fetch("/api/admin/upload", { method: "POST", body: formData });
      const result = await res.json();
      if (result.path) {
        onChange(items.map((item, i) => (i === index ? { ...item, image: result.path } : item)));
      }
    } catch { /* upload failed */ } finally {
      setUploadingIndex(null);
    }
  }

  return (
    <div>
      <label className="block text-sm text-neutral-400 mb-1.5">{label}</label>
      <div className="space-y-2">
        {items.map((item, i) => (
          <div key={i} className="rounded-lg border border-white/10 bg-neutral-800/50 p-2.5 space-y-1.5">
            <div className="flex items-center gap-1.5">
              <input
                type="text"
                value={item.text}
                onChange={(e) => updateText(i, e.target.value)}
                className="flex-1 rounded-md border border-white/10 bg-neutral-800 px-2.5 py-1.5 text-sm text-white outline-none focus:border-gold transition-colors"
              />
              <button
                type="button"
                onClick={() => remove(i)}
                className="shrink-0 rounded-md p-1.5 text-neutral-500 hover:text-red-400 transition-colors"
              >
                <X size={14} />
              </button>
            </div>
            <div className="flex items-center gap-1.5">
              {item.image ? (
                <div className="flex items-center gap-1 rounded bg-neutral-700/50 px-1.5 py-0.5 text-[11px] text-neutral-300">
                  <ImageIcon size={10} className="text-gold" />
                  <span className="max-w-[80px] truncate">{item.image.split("/").pop()}</span>
                  <button type="button" onClick={() => removeImage(i)} className="text-neutral-500 hover:text-red-400">
                    <X size={9} />
                  </button>
                </div>
              ) : (
                <label className="flex cursor-pointer items-center gap-1 rounded px-1.5 py-0.5 text-[11px] text-neutral-500 hover:text-neutral-300 transition-colors">
                  {uploadingIndex === i ? <Loader2 size={10} className="animate-spin" /> : <Upload size={10} />}
                  {uploadingIndex === i ? "..." : "Фото"}
                  <input type="file" accept="image/*" onChange={(e) => handleUpload(i, e)} className="hidden" />
                </label>
              )}
              <ValidatedLinkField
                value={item.link || ""}
                onChange={(v) => updateLink(i, v)}
                validationKey={`edu-${i}`}
                onValidate={onLinkValidate}
              />
            </div>
          </div>
        ))}
        <div className="flex items-center gap-2">
          <input
            type="text"
            value={draft}
            onChange={(e) => setDraft(e.target.value)}
            onKeyDown={(e) => { if (e.key === "Enter") { e.preventDefault(); add(); } }}
            placeholder={placeholder || "Добавить..."}
            className="flex-1 rounded-lg border border-dashed border-white/10 bg-neutral-800/50 px-4 py-2 text-sm text-white placeholder-neutral-600 outline-none focus:border-gold/50 transition-colors"
          />
          <button
            type="button"
            onClick={add}
            disabled={!draft.trim()}
            className="shrink-0 rounded-lg p-2 text-neutral-500 hover:text-gold transition-colors disabled:opacity-30"
          >
            <Plus size={14} />
          </button>
        </div>
      </div>
    </div>
  );
}

// --- Date Range Picker ---
// Parses Russian date formats: "22.02.2025", "22-23.02.2025", "22.02-01.03.2025"
function parseDateRange(value: string): { start: string; end: string } {
  if (!value) return { start: "", end: "" };

  // "22-23.02.2025" → same month range
  const sameMonth = value.match(/^(\d{1,2})-(\d{1,2})\.(\d{2})\.(\d{4})$/);
  if (sameMonth) {
    const [, d1, d2, m, y] = sameMonth;
    return {
      start: `${y}-${m}-${d1.padStart(2, "0")}`,
      end: `${y}-${m}-${d2.padStart(2, "0")}`,
    };
  }

  // "22.02-01.03.2025" → cross-month range
  const crossMonth = value.match(/^(\d{1,2})\.(\d{2})-(\d{1,2})\.(\d{2})\.(\d{4})$/);
  if (crossMonth) {
    const [, d1, m1, d2, m2, y] = crossMonth;
    return {
      start: `${y}-${m1}-${d1.padStart(2, "0")}`,
      end: `${y}-${m2}-${d2.padStart(2, "0")}`,
    };
  }

  // "22.02.2025" → single date
  const single = value.match(/^(\d{1,2})\.(\d{2})\.(\d{4})$/);
  if (single) {
    const [, d, m, y] = single;
    const iso = `${y}-${m}-${d.padStart(2, "0")}`;
    return { start: iso, end: "" };
  }

  return { start: "", end: "" };
}

function formatDateRange(start: string, end: string): string {
  if (!start) return "";
  const [sy, sm, sd] = start.split("-");
  if (!end) return `${sd}.${sm}.${sy}`;
  const [ey, em, ed] = end.split("-");
  if (sm === em && sy === ey) return `${sd}-${ed}.${sm}.${sy}`;
  return `${sd}.${sm}-${ed}.${em}.${ey}`;
}

interface DateRangeFieldProps {
  value: string;
  onChange: (value: string) => void;
}

export function DateRangeField({ value, onChange }: DateRangeFieldProps) {
  const { start, end } = parseDateRange(value);

  function handleChange(s: string, e: string) {
    onChange(formatDateRange(s, e));
  }

  return (
    <div className="flex items-center gap-1">
      <Calendar size={11} className="text-neutral-500 shrink-0" />
      <input
        type="date"
        value={start}
        onChange={(e) => handleChange(e.target.value, end)}
        className="w-[130px] rounded-md border border-white/10 bg-neutral-800 px-1.5 py-1.5 text-xs text-white outline-none focus:border-gold transition-colors [color-scheme:dark]"
      />
      <span className="text-neutral-500 text-xs">—</span>
      <input
        type="date"
        value={end}
        min={start}
        onChange={(e) => handleChange(start, e.target.value)}
        className="w-[130px] rounded-md border border-white/10 bg-neutral-800 px-1.5 py-1.5 text-xs text-white outline-none focus:border-gold transition-colors [color-scheme:dark]"
      />
    </div>
  );
}

// --- City Autocomplete Field ---
interface CityFieldProps {
  value: string;
  onChange: (value: string) => void;
  error?: string;
  onSearch?: (query: string) => void;
  suggestions?: string[];
  onSelectSuggestion?: (value: string) => void;
}

export function CityField({ value, onChange, error, onSearch, suggestions, onSelectSuggestion }: CityFieldProps) {
  const [focused, setFocused] = useState(false);
  const containerRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    if (!focused) return;
    function handle(e: MouseEvent) {
      if (containerRef.current && !containerRef.current.contains(e.target as Node)) {
        setFocused(false);
      }
    }
    document.addEventListener("mousedown", handle);
    return () => document.removeEventListener("mousedown", handle);
  }, [focused]);

  return (
    <div ref={containerRef} className="relative flex-1">
      <div className="relative">
        <MapPin size={11} className="absolute left-2 top-1/2 -translate-y-1/2 text-neutral-500 pointer-events-none" />
        <input
          type="text"
          value={value}
          onChange={(e) => {
            onChange(e.target.value);
            onSearch?.(e.target.value);
          }}
          onFocus={() => setFocused(true)}
          placeholder="Город, страна"
          className={`w-full rounded-md border bg-neutral-800 pl-6 pr-3 py-1.5 text-sm text-white placeholder-neutral-600 outline-none transition-colors ${
            error ? "border-red-500/50" : "border-white/10 focus:border-gold"
          }`}
        />
        {error && <AlertCircle size={12} className="absolute right-2 top-1/2 -translate-y-1/2 text-red-400" />}
      </div>
      {error && <p className="mt-0.5 text-[10px] text-red-400">{error}</p>}
      {focused && suggestions && suggestions.length > 0 && (
        <div className="absolute z-50 mt-1 w-full rounded-lg border border-white/10 bg-neutral-800 shadow-xl overflow-hidden">
          {suggestions.map((s) => (
            <button
              key={s}
              type="button"
              onMouseDown={(e) => e.preventDefault()}
              onClick={() => {
                onSelectSuggestion?.(s);
                setFocused(false);
              }}
              className="w-full px-3 py-1.5 text-left text-sm text-white hover:bg-white/5 transition-colors"
            >
              {s}
            </button>
          ))}
        </div>
      )}
    </div>
  );
}

// --- Link Field with Validation ---
interface ValidatedLinkFieldProps {
  value: string;
  onChange: (value: string) => void;
  onValidate?: (key: string, error: string | null) => void;
  validationKey?: string;
  placeholder?: string;
}

export function ValidatedLinkField({ value, onChange, onValidate, validationKey, placeholder }: ValidatedLinkFieldProps) {
  const [error, setError] = useState<string | null>(null);

  function validate(url: string) {
    if (!url) {
      setError(null);
      onValidate?.(validationKey || "", null);
      return;
    }
    try {
      new URL(url);
      setError(null);
      onValidate?.(validationKey || "", null);
    } catch {
      setError("Некорректная ссылка");
      onValidate?.(validationKey || "", "invalid");
    }
  }

  return (
    <div className="flex items-center gap-1.5 flex-1">
      <Link size={12} className="text-neutral-500 shrink-0" />
      <div className="relative flex-1">
        <input
          type="text"
          value={value}
          onChange={(e) => {
            onChange(e.target.value);
            validate(e.target.value);
          }}
          placeholder={placeholder || "Ссылка..."}
          className={`w-full rounded-md border bg-neutral-800 px-2 py-1 text-xs text-white placeholder-neutral-600 outline-none transition-colors ${
            error ? "border-red-500/50" : "border-white/5 focus:border-gold/50"
          }`}
        />
        {error && (
          <span className="absolute right-1.5 top-1/2 -translate-y-1/2">
            <AlertCircle size={10} className="text-red-400" />
          </span>
        )}
      </div>
    </div>
  );
}

// --- Place/Nomination Select ---
const PLACE_OPTIONS = [
  { value: "1 место", label: "1 место", icon: "🥇" },
  { value: "2 место", label: "2 место", icon: "🥈" },
  { value: "3 место", label: "3 место", icon: "🥉" },
  { value: "4 место", label: "4 место" },
  { value: "5 место", label: "5 место" },
  { value: "6 место", label: "6 место" },
  { value: "Финалист", label: "Финалист", icon: "🏅" },
  { value: "Полуфиналист", label: "Полуфиналист" },
  { value: "Лауреат", label: "Лауреат", icon: "🏆" },
  { value: "Номинант", label: "Номинант" },
  { value: "Участник", label: "Участник" },
  { value: "Победитель", label: "Победитель", icon: "🏆" },
  { value: "Гран-при", label: "Гран-при", icon: "👑" },
  { value: "Best Show", label: "Best Show", icon: "⭐" },
  { value: "Vice Champion", label: "Vice Champion" },
  { value: "Champion", label: "Champion", icon: "🏆" },
];

interface PlaceSelectProps {
  value: string;
  onChange: (value: string) => void;
}

function PlaceSelect({ value, onChange }: PlaceSelectProps) {
  const [open, setOpen] = useState(false);
  const containerRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    if (!open) return;
    function handle(e: MouseEvent) {
      if (containerRef.current && !containerRef.current.contains(e.target as Node)) setOpen(false);
    }
    document.addEventListener("mousedown", handle);
    return () => document.removeEventListener("mousedown", handle);
  }, [open]);

  const selected = PLACE_OPTIONS.find((o) => o.value === value);

  return (
    <div ref={containerRef} className="relative w-28 shrink-0">
      <button
        type="button"
        onClick={() => setOpen(!open)}
        className={`w-full rounded-md border bg-neutral-800 px-2 py-1.5 text-left text-sm transition-colors ${
          open ? "border-gold" : "border-white/10"
        } ${value ? "text-white" : "text-neutral-500"}`}
      >
        {selected ? `${selected.icon ? selected.icon + " " : ""}${selected.label}` : "Место..."}
      </button>
      {open && (
        <div className="absolute z-50 mt-1 w-44 rounded-lg border border-white/10 bg-neutral-800 shadow-xl overflow-hidden">
          <div className="max-h-52 overflow-y-auto">
            {PLACE_OPTIONS.map((opt) => (
              <button
                key={opt.value}
                type="button"
                onClick={() => { onChange(opt.value); setOpen(false); }}
                className={`w-full px-3 py-1.5 text-left text-sm transition-colors hover:bg-white/5 ${
                  opt.value === value ? "text-gold bg-gold/5" : "text-white"
                }`}
              >
                {opt.icon && <span className="mr-1.5">{opt.icon}</span>}
                {opt.label}
              </button>
            ))}
          </div>
        </div>
      )}
    </div>
  );
}

interface VictoryItemListFieldProps {
  label: string;
  items: VictoryItem[];
  onChange: (items: VictoryItem[]) => void;
  cityErrors?: Record<number, string>;
  citySuggestions?: { index: number; items: string[] } | null;
  onCitySearch?: (index: number, query: string) => void;
  onCitySelect?: (index: number, value: string) => void;
  onLinkValidate?: (key: string, error: string | null) => void;
}

export function VictoryItemListField({ label, items, onChange, cityErrors, citySuggestions, onCitySearch, onCitySelect, onLinkValidate }: VictoryItemListFieldProps) {
  function add() {
    onChange([...items, { place: "", category: "", competition: "" }]);
  }

  function remove(index: number) {
    onChange(items.filter((_, i) => i !== index));
  }

  function update(index: number, field: keyof VictoryItem, value: string) {
    onChange(items.map((item, i) => (i === index ? { ...item, [field]: value || undefined } : item)));
  }

  return (
    <div>
      <label className="block text-sm text-neutral-400 mb-1.5">{label}</label>
      <div className="space-y-3">
        {items.map((item, i) => (
          <div key={i} className="rounded-lg border border-white/10 bg-neutral-800/50 p-2.5 space-y-1.5">
            <div className="flex gap-1.5">
              <PlaceSelect
                value={item.place || ""}
                onChange={(v) => update(i, "place", v)}
              />
              <input
                type="text"
                value={item.category || ""}
                onChange={(e) => update(i, "category", e.target.value)}
                placeholder="Категория"
                className="flex-1 rounded-md border border-white/10 bg-neutral-800 px-2.5 py-1.5 text-sm text-white placeholder-neutral-600 outline-none focus:border-gold transition-colors"
              />
              <input
                type="text"
                value={item.competition || ""}
                onChange={(e) => update(i, "competition", e.target.value)}
                placeholder="Чемпионат"
                className="flex-1 rounded-md border border-white/10 bg-neutral-800 px-2.5 py-1.5 text-sm text-white placeholder-neutral-600 outline-none focus:border-gold transition-colors"
              />
              <button
                type="button"
                onClick={() => remove(i)}
                className="shrink-0 rounded-md p-1.5 text-neutral-500 hover:text-red-400 transition-colors"
              >
                <X size={14} />
              </button>
            </div>
            <div className="flex gap-1.5">
              <CityField
                value={item.location || ""}
                onChange={(v) => update(i, "location", v)}
                error={cityErrors?.[i]}
                onSearch={(q) => onCitySearch?.(i, q)}
                suggestions={citySuggestions?.index === i ? citySuggestions.items : undefined}
                onSelectSuggestion={(v) => onCitySelect?.(i, v)}
              />
              <DateRangeField
                value={item.date || ""}
                onChange={(v) => update(i, "date", v)}
              />
            </div>
            <ValidatedLinkField
              value={item.link || ""}
              onChange={(v) => update(i, "link", v)}
              validationKey={`victory-${i}`}
              onValidate={onLinkValidate}
            />
          </div>
        ))}
        <button
          type="button"
          onClick={add}
          className="flex items-center gap-2 rounded-lg border border-dashed border-white/10 bg-neutral-800/50 px-4 py-2 text-sm text-neutral-500 hover:text-gold hover:border-gold/30 transition-colors"
        >
          <Plus size={14} />
          Добавить достижение
        </button>
      </div>
    </div>
  );
}
