"use client";

import { useState, useEffect, useRef, useCallback } from "react";
import { Loader2, Check, AlertCircle } from "lucide-react";
import { adminFetch } from "@/lib/csrf";

interface SectionEditorProps<T> {
  sectionKey: string;
  title: string;
  defaultData?: Partial<T>;
  /** Return true if data is valid and can be saved. Blocks auto-save when false. */
  validate?: (data: T) => boolean;
  children: (data: T, update: (data: T) => void) => React.ReactNode;
}

const DEBOUNCE_MS = 800;

export function SectionEditor<T>({
  sectionKey,
  title,
  defaultData,
  validate,
  children,
}: SectionEditorProps<T>) {
  const [data, setData] = useState<T | null>(null);
  const [loading, setLoading] = useState(true);
  const [status, setStatus] = useState<"idle" | "saving" | "saved" | "error">("idle");
  const [error, setError] = useState("");
  const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
  const initialLoadRef = useRef(true);

  useEffect(() => {
    adminFetch(`/api/admin/sections/${sectionKey}`)
      .then((r) => {
        if (!r.ok) throw new Error("Failed to load");
        return r.json();
      })
      .then((loaded) => setData(defaultData ? { ...defaultData, ...loaded } as T : loaded))
      .catch(() => setError("Не удалось загрузить данные"))
      .finally(() => setLoading(false));
  }, [sectionKey]);

  const save = useCallback(async (dataToSave: T) => {
    setStatus("saving");
    setError("");

    try {
      const res = await adminFetch(`/api/admin/sections/${sectionKey}`, {
        method: "PUT",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(dataToSave),
      });
      if (!res.ok) throw new Error("Failed to save");
      setStatus("saved");
      setTimeout(() => setStatus((s) => (s === "saved" ? "idle" : s)), 2000);
    } catch {
      setStatus("error");
      setError("Ошибка сохранения");
      setTimeout(() => setStatus((s) => (s === "error" ? "idle" : s)), 4000);
    }
  }, [sectionKey]);

  // Auto-save with debounce whenever data changes (skip initial load)
  useEffect(() => {
    if (!data) return;
    if (initialLoadRef.current) {
      initialLoadRef.current = false;
      return;
    }

    if (timerRef.current) clearTimeout(timerRef.current);
    timerRef.current = setTimeout(() => {
      if (validate && !validate(data)) return;
      save(data);
    }, DEBOUNCE_MS);

    return () => {
      if (timerRef.current) clearTimeout(timerRef.current);
    };
  }, [data, save]);

  if (loading) {
    return (
      <div className="flex items-center gap-2 text-neutral-400">
        <Loader2 size={18} className="animate-spin" />
        Загрузка...
      </div>
    );
  }

  if (!data) {
    return <p className="text-red-400">{error || "Данные не найдены"}</p>;
  }

  return (
    <div>
      <h1 className="text-2xl font-bold">{title}</h1>

      {/* Fixed toast popup */}
      {(status === "saved" || status === "error") && (
        <div role="status" aria-live="polite" className={`fixed bottom-4 right-4 z-50 flex items-center gap-2 rounded-lg border px-3 py-2 text-sm shadow-lg animate-in slide-in-from-right ${
          status === "saved"
            ? "bg-emerald-950/90 border-emerald-500/30 text-emerald-200"
            : "bg-red-950/90 border-red-500/30 text-red-200"
        }`}>
          {status === "saved" && <><Check size={14} /> Сохранено</>}
          {status === "error" && <><AlertCircle size={14} /> {error}</>}
        </div>
      )}

      <div className="mt-6 space-y-6">{children(data, setData)}</div>
    </div>
  );
}
